@ManfredSteyerModern Angular:Architectures with Standalone ComponentsManfredSteyer
View Slide
@ManfredSteyer
@ManfredSteyerManfred Steyer
@ManfredSteyerNgModules + EcmaScript Modulesimport { NgModule } from '@angular/core';import { BrowserModule } from '@angular/platform-browser';import { AppComponent } from './app.component';[…]@NgModule({imports: [BrowserModule, OtherModule],declarations: [AppComponent, OtherComponent, OtherDirective],providers: [],bootstrap: [AppComponent],})export class AppModule {}TypeScript ModulesAngular Modules
@ManfredSteyer@Component({standalone: true,imports: [[…],FlightCardComponent,CityPipe,CityValidator,],selector: 'flight-search',templateUrl: '…'})export class FlightSearchComponent {[…]}
@ManfredSteyerSmall and Medium Apps:Folder per Feature
@ManfredSteyerMedium and Large Apps:Folder per Domain
@ManfredSteyer→@Component({standalone: true,selector: 'app-root',imports: [[…]TicketsModule,],templateUrl: '…'})export class AppComponent {}
@ManfredSteyer→@NgModule({imports: [FlightCardComponent,],declarations: [MyTicketsComponent],})export class TicketsModule { }
@ManfredSteyerbootstrapApplication(AppComponent, {providers: [MyGlobalService,importProvidersFrom(MyModule),]});
@ManfredSteyerng g @angular/core:standalone
@ManfredSteyerbootstrapApplication(AppComponent, {providers: [[…]]});
@ManfredSteyerbootstrapApplication(AppComponent, {providers: [importProvidersFrom(HttpClientModule),importProvidersFrom(RouterModule.forRoot(APP_ROUTES)),]});
@ManfredSteyerbootstrapApplication(AppComponent, {providers: [provideHttpClient(),provideRouter(APP_ROUTES),]});
@ManfredSteyerbootstrapApplication(AppComponent, {providers: [provideHttpClient(withInterceptors([authInterceptor]),),provideRouter(APP_ROUTES,withPreloading(PreloadAllModules),withDebugTracing(),),]});
@ManfredSteyerbootstrapApplication(AppComponent, {providers: [provideLogger(loggerConfig),]});
@ManfredSteyerbootstrapApplication(AppComponent, {providers: [provideLogger(loggerConfig,withColor({ debug: 3 })),]});
@ManfredSteyerexport function provideLogger(config: LoggerConfig): Provider[] {[…]}
@ManfredSteyerexport function provideLogger(config: LoggerConfig): Provider[] {return [LoggerService,{provide: LoggerConfig,useValue: config},{provide: LogFormatter,useValue: config.formatter},];}
@ManfredSteyerexport function provideLogger(config: LoggerConfig): EnvironmentProviders {return makeEnvironmentProviders([LoggerService,{provide: LoggerConfig,useValue: config},{provide: LogFormatter,useValue: config.formatter},]);}
@ManfredSteyerexport function provideLogger(config: LoggerConfig, ...featues: LoggerFeature[]): EnvironmentProviders {return makeEnvironmentProviders([LoggerService,[…],features?.map(f => f.providers)]);}
@ManfredSteyerexport const APP_ROUTES: Routes = [[…]{path: 'flight-booking',canActivate: [() => inject(AuthService).isAuthenticated()],component: FlightBookingComponent},]
@ManfredSteyerexport const APP_ROUTES: Routes = [[…]{path: 'flight-booking',canActivate: [() => inject(AuthService).isAuthenticated()],resolve: {flights: () => inject(FlightService).findAll()},component: FlightBookingComponent},]
@ManfredSteyerexport const authInterceptor: HttpInterceptorFn = (req, next) => {[…]}
@ManfredSteyerexport const authInterceptor: HttpInterceptorFn = (req, next) => {if (req.url.startsWith('https://[…]/')) {const headers = req.headers.set('Authorization', 'Bearer 12345');req = req.clone({headers});}[…]}
@ManfredSteyerexport const authInterceptor: HttpInterceptorFn = (req, next) => {if (req.url.startsWith('https://[…]/')) {const headers = req.headers.set('Authorization', 'Bearer 12345');req = req.clone({headers});}return next(req);}
@ManfredSteyerexport const authInterceptor: HttpInterceptorFn = (req, next) => {if (req.url.startsWith('https://[…]/')) {const headers = req.headers.set('Authorization', 'Bearer 12345');req = req.clone({headers});}return next(req).pipe(tap(resp => console.log('response', resp)));}
@ManfredSteyerbootstrapApplication(AppComponent, {providers: [provideHttpClient(withInterceptors([authInterceptor]),),]});
@ManfredSteyerbootstrapApplication(AppComponent, {providers: [provideLogger({level: LogLevel.DEBUG,appenders: [DefaultLogAppender],formatter: (level, cat, msg) => [level, cat, msg].join(';'),}),]});
@ManfredSteyerFree eBook (brand new)ANGULARarchitects.io/standalone-bookStandalone ComponentsDownload here:
@ManfredSteyerZone.js:MonkeyPatchingAfter EventHandler:Inform AngularCD checksComponentsall components (default)or selected ones (OnPush)
@ManfredSteyerZone.js:MagicZone.js:~100KCannot patchasync/awaitcoarsegrained CDe.g. Components are always checked as awhole, even if only a tiny fraction changed
@ManfredSteyerSignals!
@ManfredSteyerSignal4711Consumerreadsetnotify4712
@ManfredSteyerflights: Flight[] = [];const flights = await this.flightService.findAsPromise(from, to);this.flights = flights;
@ManfredSteyerflights = signal([]);const flights = await this.flightService.findAsPromise(from, to);this.flights.set(flights);
@ManfredSteyerSignals are in anEarly Stage!It will an option;no need to updateexisting code!
@ManfredSteyerFine-grainedand Zone-lessCDConvertible toObservablesand vice versa!No need tounsubscribe!
@ManfredSteyerModern Angular:LightweightArchitecturesStandaloneComponentsand APIsFunctional ServicesUpcoming:Signals
@ManfredSteyerdSlides & Examples Remote Company Workshopsand Consultinghttp://angulararchitects.io