Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
Better Angular Architectures: Architectures with Standalone Components @DWX2022
Manfred Steyer
PRO
July 05, 2022
Programming
1
480
Better Angular Architectures: Architectures with Standalone Components @DWX2022
Manfred Steyer
PRO
July 05, 2022
Tweet
Share
More Decks by Manfred Steyer
See All by Manfred Steyer
More Than Micro Frontends: 3 Further Use Cases for Module Federation @DWX 2022
manfredsteyer
PRO
0
420
Angular‘s Future without NgModules: Architectures with Standalone Components @enterJS
manfredsteyer
PRO
0
300
Beyond Micro Frontends: Frontend Moduliths for the Enterprise @enterjs2022
manfredsteyer
PRO
0
380
Angular-basierte Micro Frontends mit Module Federation @API Summit
manfredsteyer
PRO
0
150
Beyond Micro Frontends: Frontend Moduliths for the Enterprise @wad2022
manfredsteyer
PRO
0
180
Sustainable SPAs with Strategic Design: A Wonderful Friendship?
manfredsteyer
PRO
0
150
Micro Frontends with Module Federation: Beyond the Basics @codecrafts2022
manfredsteyer
PRO
0
300
Rethinking Auth for SPAs and Micro Frontends: Easy and Secure With Gateways
manfredsteyer
PRO
0
210
Micro Frontends with Module Federation: Beyond the Basics @jax2022
manfredsteyer
PRO
1
370
Other Decks in Programming
See All in Programming
クラウド KMS の活用 / TOKYO BLOCKCHAIN TECH MEETUP 2022
odanado
PRO
0
200
WindowsコンテナDojo:第6回 Red Hat OpenShift入門
oniak3ibm
PRO
0
180
SRE NEXT 2022に学ぶこれからのSREキャリア
fukubaka0825
2
400
ECサイトの脆弱性診断をいい感じにやりたい/OWASPKansaiNight_LT1_220727
owaspkansai
0
310
Google IO 2022 社内LT会 / What's new in Android development tools
shingo_kobayashi
1
430
設計の考え方とやり方
masuda220
PRO
56
32k
2022年のモダンCSS改
tonkotsuboy_com
24
17k
How to start contributing to Kubernetes Projects
ydfu
0
150
How to Test Your Compose UI (Droidcon Berlin 2022)
stewemetal
1
140
테라폼으로 ECR 관리하기 (How to Manage ECR with Terraform)
posquit0
0
530
kintoneでランダム取得を作ってみた(imoniCamp 2022-07-27)
shokun1108
0
150
Untangling Coroutine Testing (Droidcon Berlin 2022)
zsmb
2
500
Featured
See All Featured
Navigating Team Friction
lara
175
11k
Statistics for Hackers
jakevdp
782
210k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
351
21k
Intergalactic Javascript Robots from Outer Space
tanoku
260
25k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
349
27k
A designer walks into a library…
pauljervisheath
197
16k
Why You Should Never Use an ORM
jnunemaker
PRO
47
7.7k
A Modern Web Designer's Workflow
chriscoyier
689
180k
Designing with Data
zakiwarfel
91
4k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
29
4.4k
Debugging Ruby Performance
tmm1
65
10k
Git: the NoSQL Database
bkeepers
PRO
415
59k
Transcript
@ManfredSteyer Better Angular Architectures: Architectures with Standalone Components
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer Angular 2 BETA, Feb 2016 @Component({ selector: 'app', directives:
[ROUTER_DIRECTIVES, MyComponent, NgIf, NgFor], templateUrl: 'app/app.html' }) @RouteConfig([ { path: '/', component: Home, … }, { path: '/voucher', component: Voucher, … }, ]) export class App { […] }
@ManfredSteyer Angular 2 RC.5, August 2016 import { 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 {}
@ManfredSteyer Angular 2 RC.5, August 2016 import { 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 {}
@ManfredSteyer Angular 2 RC.5, August 2016 import { 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 Modules Angular Modules
@ManfredSteyer My Ivy Talk at ng-conf 2020
@ManfredSteyer @Component({ standalone: true, selector: 'app-root', imports: [ HomeComponent, AboutComponent,
HttpClientModule, ], templateUrl: '…' }) export class AppComponent { […] }
@ManfredSteyer bootstrapApplication(AppComponent);
@ManfredSteyer
@ManfredSteyer #1 Mental Model #2 Compatibility #3 Routing #4 Architecture
@ManfredSteyer Manfred Steyer
@ManfredSteyer
@ManfredSteyer Standalone Component = Component + NgModule (not implemented that
way!)
@ManfredSteyer @Component({ standalone: true, selector: 'app-root', imports: [ RouterModule, HomeComponent,
AboutComponent, ], templateUrl: '…' }) export class AppComponent { […] } @NgModule({ imports: [ RouterModule, HomeComponentModule, AboutComponentModule, ], declares: [ AppComponent ] }) export class AppModule { … } @Component({ selector: 'app-root', templateUrl: '…' }) export class AppComponent { […] }
@ManfredSteyer @Pipe({ standalone: true, name: 'city', pure: true }) export
class CityPipe implements PipeTransform { […] }
@ManfredSteyer @Directive({ standalone: true, selector: 'input[appCity]', providers: [ … ]
}) export class CityValidator implements Validator { […] }
@ManfredSteyer @Component({ standalone: true, imports: [ […], FlightCardComponent, CityPipe, CityValidator,
], selector: 'flight-search', templateUrl: '…' }) export class FlightSearchComponent { […] }
@ManfredSteyer
@ManfredSteyer It looks like you want to use NgIfDirective and
MyComponent. Shall I import it for you?
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer → @Component({ standalone: true, selector: 'app-root', imports: [ […]
TicketsModule, ], templateUrl: '…' }) export class AppComponent { }
@ManfredSteyer → @Component({ standalone: true, selector: 'app-root', imports: [ […]
TicketsModule, ], templateUrl: '…' }) export class AppComponent { }
@ManfredSteyer → @NgModule({ imports: [ FlightCardComponent, ], declarations: [ MyTicketsComponent
], }) export class TicketsModule { }
@ManfredSteyer → @NgModule({ imports: [ FlightCardComponent, ], declarations: [ MyTicketsComponent
], }) export class TicketsModule { }
@ManfredSteyer bootstrapApplication(AppComponent, { providers: [ MyGlobalService, importProvidersFrom(HttpClientModule), importProvidersFrom(RouterModule.forRoot(APP_ROUTES)), ] });
@ManfredSteyer bootstrapApplication(AppComponent, { providers: [ MyGlobalService, importProvidersFrom(HttpClientModule), importProvidersFrom(RouterModule.forRoot(APP_ROUTES)), ] });
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer bootstrapApplication(AppComponent, { providers: [ MyGlobalService, importProvidersFrom(HttpClientModule), importProvidersFrom(RouterModule.forRoot(APP_ROUTES)), ] });
@ManfredSteyer bootstrapApplication(AppComponent, { providers: [ MyGlobalService, importProvidersFrom(HttpClientModule), provideRoutes(APP_ROUTES), ] });
@ManfredSteyer export const APP_ROUTES: Routes = [ […], { path:
'flight-booking', loadChildren: () => import('@nx-example/booking/feature-book') .then(m => m.FLIGHT_BOOKING_ROUTES) }, { path: 'next-flight', loadComponent: () => import('@nx-example/booking/feature-tickets') .then(m => m.NextFlightComponent) }, ];
@ManfredSteyer export const APP_ROUTES: Routes = [ […], { path:
'flight-booking', loadChildren: () => import('@nx-example/booking/feature-book') .then(m => m.FLIGHT_BOOKING_ROUTES) }, { path: 'next-flight', loadComponent: () => import('@nx-example/booking/feature-tickets') .then(m => m.NextFlightComponent) }, ];
@ManfredSteyer export const FLIGHT_BOOKING_ROUTES: Routes = [{ path: '', component:
FlightBookingComponent, providers: [ MyService ], children: [ […] ] }];
@ManfredSteyer export const FLIGHT_BOOKING_ROUTES: Routes = [{ path: '', component:
FlightBookingComponent, providers: [ MyService ], children: [ […] ] }]; (Lazily) loaded with route config Scope: This route + all child routes
@ManfredSteyer export const FLIGHT_BOOKING_ROUTES: Routes = [{ path: '', component:
FlightBookingComponent, providers: [ ...configureMyLibrary() ], children: [ […] ] }];
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer // index.ts == Public API export * from './flight-booking.component';
export * from './flight-card/flight-card.component';
@ManfredSteyer
@ManfredSteyer import * as booking from './booking'; […] @Component({ standalone:
true, imports: [ booking, […] ], […] }) export class MyComponent { […] } Wish List
@ManfredSteyer
@ManfredSteyer "paths": { "@demo/data": ["src/app/data/index.ts"], "@demo/shared": ["src/app/shared/index.ts"], "@demo/shell": ["src/app/shell/index.ts"], "@demo/booking":
["src/app/booking/index.ts"] }
@ManfredSteyer import * as booking from '@demo/booking'; […] @Component({ standalone:
true, imports: [ ...Object.values(booking) as any[], […] ], […] }) export class MyComponent { […] }
@ManfredSteyer
@ManfredSteyer + Generates path mappings + Generates initial barrel +
Prevents bypassing index.ts + much more
@ManfredSteyer
@ManfredSteyer Booking Boarding Shared Feature Feature Feature Feature Feature UI
UI UI UI UI UI UI UI UI Domain Domain Domain Domain Domain Domain Util Util Util Util Util Util @ManfredSteyer
@ManfredSteyer Free eBook (5th Edition) ANGULARarchitects.io/book Module Federation & Nx
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
@ManfredSteyer Lib A Lib B index.ts Comp1 Comp2 Today (with
NgModules) NgModule Comp3 NgModule
@ManfredSteyer Lib A Lib B index.ts Comp1 Comp2 Tomorrow (without
NgModules) Comp3
@ManfredSteyer Conclusion Mental Model Folders & Barrels Mapped Paths Nx,
Libs, and Constraints FTW!
@ManfredSteyer 2022
@ManfredSteyer d Slides & Examples Remote Company Workshops and Consulting
http://angulararchitects.io