Santosh Yadav
Google Developer Expert for Angular GitHub Start and Nx Champion, Open source contributor for Angular and NgRx, creator ng deploy for Netlify, NestJSAddons core team.
Santosh Yadav
GDE for Angular, GitHub Star, Auth0 Amabassador
Co-founder This is Learning
Use TrackBy with ngFor
OnPush Change Detection
Signals
@Component({
selector: 'app-product-signal',
templateUrl: './product-signal.component.html',
styleUrls: ['./product-signal.component.scss'],
standalone: true,
imports: [JsonPipe, CommonModule],
})
export class ProductSignalComponent implements OnInit {
product = signal<Product[]>([]);
addProduct() {
this.product.set(
[{
id: crypto.randomUUID(),
name: 'product 1',
price: 100,
description: 'test',
}]
);
}
}
How Lazy Loading Helps
Seperate feature bundles
Load bundles on demand
Serve less code on first serve
Configure lazy-loading with Module
const routes: Routes = [
{
path: 'rooms',
loadChildren: () =>
import('./rooms/rooms.module').then((m) => m.RoomsModule),
canActivate: [LoginGuard],
canLoad: [LoginGuard],
}
];
Configure lazy-loading with Standalone Component
const routes: Routes = [
{
path: 'rooms',
loadComponent: () => import('./comment/comment.component').then((m) => m.CommentComponent),
canActivate: [LoginGuard],
canLoad: [LoginGuard],
}
];
Avoid Shared Module
Text
import { NgModule } from '@angular/core';
import { OverlayModule } from '@angular/cdk/overlay';
import { CdkTreeModule } from '@angular/cdk/tree';
import { PortalModule } from '@angular/cdk/portal';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatButtonModule } from '@angular/material/button';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatCardModule } from '@angular/material/card';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatChipsModule } from '@angular/material/chips';
import { MatRippleModule } from '@angular/material/core';
import { MatDividerModule } from '@angular/material/divider';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatListModule } from '@angular/material/list';
import { MatMenuModule } from '@angular/material/menu';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSelectModule } from '@angular/material/select';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { MatTabsModule } from '@angular/material/tabs';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatTreeModule } from '@angular/material/tree';
const materialModules = [
CdkTreeModule,
MatAutocompleteModule,
MatButtonModule,
MatCardModule,
MatCheckboxModule,
MatChipsModule,
MatDividerModule,
MatExpansionModule,
MatIconModule,
MatInputModule,
MatListModule,
MatMenuModule,
MatProgressSpinnerModule,
MatPaginatorModule,
MatRippleModule,
MatSelectModule,
MatSidenavModule,
MatSnackBarModule,
MatSortModule,
MatTableModule,
MatTabsModule,
MatToolbarModule,
MatFormFieldModule,
MatButtonToggleModule,
MatTreeModule,
OverlayModule,
PortalModule
];
@NgModule({
imports: [
...materialModules
],
exports: [
...materialModules
],
})
export class MaterialModule {
}
Secondary Entrypoints
Why
With Angular Libraries you get single entrypoints.
Even a single module or component import will add huge chunk to bundle
How
Secondary Entrypoints adds only what is imported
To configure secondary entrypoints add ng-package.json to folder
nx g library-secondary-entrypoint <sec-name>
Use Standalone Component
@Component({
selector: 'app-product-signal',
templateUrl: './product-signal.component.html',
styleUrls: ['./product-signal.component.scss'],
standalone: true,
imports: [JsonPipe, CommonModule],
})
export class ProductSignalComponent
implements OnInit {
}
ng generate @angular/core:standalone
Migration to Standalone
Always Check What's in your bundle
How
Use source-map-explorer
ng add @ngx-builders/analyze
ng run project-name:analyze
Always use budgets
"budgets": [
{
"type": "initial",
"maximumWarning": "100kb",
"maximumError": "150kb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
Types of budgets
bundle - The size of a specific bundle.
initial - The initial size of the app.
allScript - The size of all scripts.
all - The size of the entire app.
Types of budgets
anyComponentStyle - This size of any one component stylesheet.
anyScript - The size of any one script.
any - The size of any file.
State Management
Available Solutions
Always use es modules for lodash or moments
Avoid using commonjs modules.
Angular 10+ will give warnings if commonjs module is used
use allowedCommonJsDependencies to disable warning
Tree shakable
Image Optimization
@Component({
standalone: true
imports: [NgOptimizedImage],
})
class MyStandaloneComponent {}
providers: [
provideImgixLoader("https://abc.com/"),
],
<img ngSrc="logo.png" width="200" height="100">
Use Strict Mode
ng generate application [project-name] --strict
use CDN to serve the assets
Low network latency
High availability and better analytics
Decrease server load
Virtual Scroll
Available Solutions
References
https://indepth.dev/are-you-using-scss-properly/
https://indepth.dev/stop-using-shared-material-module/
twitter.com/SantoshYadavDev
github.com/SantoshYadavDev
https://www.linkedin.com/in/SantoshYadavDev/
santoshyadav.dev
Thank you
By Santosh Yadav
Google Developer Expert for Angular GitHub Start and Nx Champion, Open source contributor for Angular and NgRx, creator ng deploy for Netlify, NestJSAddons core team.