$ ng build --prod
$ ng build --prod --source-map
$ npx source-map-explorer main.bundle.js
const appRoutes: Routes = [{
path: 'tweets',
loadChildren: 'tweets/tweets.module#TweetsModule'
}]
const tweetsRoutes: Routes = [{
path: '',
component: TweetFeedsComponent
}];
@NgModule({
imports: [RouterModule.forRoot(appRoutes, {
preloadingStrategy: PreloadAllModules
})],
exports: [RouterModule]
})
First meaningful paint
First meaningful paint
No SSR
SSR
<app-root>Loading</app-root>
Loading
$ ng add @ng-toolkit/universal
$ npm run build:prod
$ npm run server
$ ng generate universal --client-project=ssr
...and follow the guide at https://angular.io/guide/universal
Change detection
UI render
Trigger
Ready
<span>{{ relativeDate(tweet.createdAt) }}</span>
<span>{{ tweet.createdAt | relativeDate }}</span>
By default
By default
By default
By default
import { ..., ChangeDetectionStrategy } from '@angular/core';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush
})
import { ..., ChangeDetectorRef } from '@angular/core';
class RealTimeList {
constructor(private ref: ChangeDetectorRef) {
ref.detach();
setInterval(() => {
this.ref.detectChanges();
}, 1000);
}
}
import { ..., NgZone } from '@angular/core';
class MyComponent implements OnChanges {
constructor(private _ngZone: NgZone ) {}
log() {
this._ngZone.runOutsideAngular(() => {
// Any code will not cause CD
}}));
}
}
export class TweetListComponent implements OnInit {
...
trackById(index, tweet) {
return tweet.id;
}
}
<div *ngFor="let tweet of tweets; trackBy: trackById">