$ ng build --prod$ ng build --prod --source-map
$ npx source-map-explorer main.bundle.jsconst 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">