Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Scalable architectures in Angular with Nx

Scalable architectures in Angular with Nx

The larger your Angular application becomes, the greater the challenges of maintaining a scalable and maintainable code base. Without a well-thought-out architecture, complexity can quickly get out of control, leading to poor applications and delays in development. In this talk, Fabian Gosebrink shows how to build scalable and modular architectures for Angular applications with Nx. We'll learn how Nx helps us organize large codebases into manageable libraries, split code, and improve team collaboration. We'll cover best practices for setting up workspaces, leveraging Nx's powerful tools, and optimizing your development process. By the end of this session, developers will have a clear understanding of how to structure Angular applications with Nx to ensure long-term maintainability, better performance, and easier collaboration for small and large teams.

Fabian Gosebrink

March 06, 2025
Tweet

More Decks by Fabian Gosebrink

Other Decks in Technology

Transcript

  1. Feature Container Ui Domain Utils ... Container Components Presentational Components

    Models, services, state Utility Functions You name it!
  2. @Component({ /* ... */ }) export class MainDoggoComponent implements OnInit

    { doggoId = input(''); store = inject(DoggosStore); private readonly destroyRef = inject(DestroyRef); ngOnInit(): void { this.store.loadDoggos(this.doggoId()); this.store.startListeningToRealtimeDoggoEvents(); this.destroyRef.onDestroy(() => { this.store.stopListeningToRealtimeDoggoEvents(); }); } rateDoggo(rating: number): void { this.store.rateDoggo(rating); } skipDoggo(): void { this.store.selectNextDoggo(); } selectDoggo(id: string): void { this.store.selectDoggo(id); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
  3. @Component({ /* ... */ }) export class MainDoggoComponent implements OnInit

    { doggoId = input(''); store = inject(DoggosStore); private readonly destroyRef = inject(DestroyRef); ngOnInit(): void { this.store.loadDoggos(this.doggoId()); this.store.startListeningToRealtimeDoggoEvents(); this.destroyRef.onDestroy(() => { this.store.stopListeningToRealtimeDoggoEvents(); }); } rateDoggo(rating: number): void { this.store.rateDoggo(rating); } skipDoggo(): void { this.store.selectNextDoggo(); } selectDoggo(id: string): void { this.store.selectDoggo(id); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 doggoId = input(''); @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 3 store = inject(DoggosStore); 4 private readonly destroyRef = inject(DestroyRef); 5 6 ngOnInit(): void { 7 this.store.loadDoggos(this.doggoId()); 8 this.store.startListeningToRealtimeDoggoEvents(); 9 10 this.destroyRef.onDestroy(() => { 11 this.store.stopListeningToRealtimeDoggoEvents(); 12 }); 13 } 14 15 rateDoggo(rating: number): void { 16 this.store.rateDoggo(rating); 17 } 18 19 skipDoggo(): void { 20 this.store.selectNextDoggo(); 21 } 22 23 selectDoggo(id: string): void { 24 this.store.selectDoggo(id); 25 } 26 } 27
  4. @Component({ /* ... */ }) export class MainDoggoComponent implements OnInit

    { doggoId = input(''); store = inject(DoggosStore); private readonly destroyRef = inject(DestroyRef); ngOnInit(): void { this.store.loadDoggos(this.doggoId()); this.store.startListeningToRealtimeDoggoEvents(); this.destroyRef.onDestroy(() => { this.store.stopListeningToRealtimeDoggoEvents(); }); } rateDoggo(rating: number): void { this.store.rateDoggo(rating); } skipDoggo(): void { this.store.selectNextDoggo(); } selectDoggo(id: string): void { this.store.selectDoggo(id); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 doggoId = input(''); @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 3 store = inject(DoggosStore); 4 private readonly destroyRef = inject(DestroyRef); 5 6 ngOnInit(): void { 7 this.store.loadDoggos(this.doggoId()); 8 this.store.startListeningToRealtimeDoggoEvents(); 9 10 this.destroyRef.onDestroy(() => { 11 this.store.stopListeningToRealtimeDoggoEvents(); 12 }); 13 } 14 15 rateDoggo(rating: number): void { 16 this.store.rateDoggo(rating); 17 } 18 19 skipDoggo(): void { 20 this.store.selectNextDoggo(); 21 } 22 23 selectDoggo(id: string): void { 24 this.store.selectDoggo(id); 25 } 26 } 27 store = inject(DoggosStore); @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 doggoId = input(''); 3 4 private readonly destroyRef = inject(DestroyRef); 5 6 ngOnInit(): void { 7 this.store.loadDoggos(this.doggoId()); 8 this.store.startListeningToRealtimeDoggoEvents(); 9 10 this.destroyRef.onDestroy(() => { 11 this.store.stopListeningToRealtimeDoggoEvents(); 12 }); 13 } 14 15 rateDoggo(rating: number): void { 16 this.store.rateDoggo(rating); 17 } 18 19 skipDoggo(): void { 20 this.store.selectNextDoggo(); 21 } 22 23 selectDoggo(id: string): void { 24 this.store.selectDoggo(id); 25 } 26 } 27
  5. @Component({ /* ... */ }) export class MainDoggoComponent implements OnInit

    { doggoId = input(''); store = inject(DoggosStore); private readonly destroyRef = inject(DestroyRef); ngOnInit(): void { this.store.loadDoggos(this.doggoId()); this.store.startListeningToRealtimeDoggoEvents(); this.destroyRef.onDestroy(() => { this.store.stopListeningToRealtimeDoggoEvents(); }); } rateDoggo(rating: number): void { this.store.rateDoggo(rating); } skipDoggo(): void { this.store.selectNextDoggo(); } selectDoggo(id: string): void { this.store.selectDoggo(id); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 doggoId = input(''); @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 3 store = inject(DoggosStore); 4 private readonly destroyRef = inject(DestroyRef); 5 6 ngOnInit(): void { 7 this.store.loadDoggos(this.doggoId()); 8 this.store.startListeningToRealtimeDoggoEvents(); 9 10 this.destroyRef.onDestroy(() => { 11 this.store.stopListeningToRealtimeDoggoEvents(); 12 }); 13 } 14 15 rateDoggo(rating: number): void { 16 this.store.rateDoggo(rating); 17 } 18 19 skipDoggo(): void { 20 this.store.selectNextDoggo(); 21 } 22 23 selectDoggo(id: string): void { 24 this.store.selectDoggo(id); 25 } 26 } 27 store = inject(DoggosStore); @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 doggoId = input(''); 3 4 private readonly destroyRef = inject(DestroyRef); 5 6 ngOnInit(): void { 7 this.store.loadDoggos(this.doggoId()); 8 this.store.startListeningToRealtimeDoggoEvents(); 9 10 this.destroyRef.onDestroy(() => { 11 this.store.stopListeningToRealtimeDoggoEvents(); 12 }); 13 } 14 15 rateDoggo(rating: number): void { 16 this.store.rateDoggo(rating); 17 } 18 19 skipDoggo(): void { 20 this.store.selectNextDoggo(); 21 } 22 23 selectDoggo(id: string): void { 24 this.store.selectDoggo(id); 25 } 26 } 27 ngOnInit(): void { this.store.loadDoggos(this.doggoId()); this.store.startListeningToRealtimeDoggoEvents(); this.destroyRef.onDestroy(() => { this.store.stopListeningToRealtimeDoggoEvents(); }); } @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 doggoId = input(''); 3 store = inject(DoggosStore); 4 private readonly destroyRef = inject(DestroyRef); 5 6 7 8 9 10 11 12 13 14 15 rateDoggo(rating: number): void { 16 this.store.rateDoggo(rating); 17 } 18 19 skipDoggo(): void { 20 this.store.selectNextDoggo(); 21 } 22 23 selectDoggo(id: string): void { 24 this.store.selectDoggo(id); 25 } 26 } 27
  6. @Component({ /* ... */ }) export class MainDoggoComponent implements OnInit

    { doggoId = input(''); store = inject(DoggosStore); private readonly destroyRef = inject(DestroyRef); ngOnInit(): void { this.store.loadDoggos(this.doggoId()); this.store.startListeningToRealtimeDoggoEvents(); this.destroyRef.onDestroy(() => { this.store.stopListeningToRealtimeDoggoEvents(); }); } rateDoggo(rating: number): void { this.store.rateDoggo(rating); } skipDoggo(): void { this.store.selectNextDoggo(); } selectDoggo(id: string): void { this.store.selectDoggo(id); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 doggoId = input(''); @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 3 store = inject(DoggosStore); 4 private readonly destroyRef = inject(DestroyRef); 5 6 ngOnInit(): void { 7 this.store.loadDoggos(this.doggoId()); 8 this.store.startListeningToRealtimeDoggoEvents(); 9 10 this.destroyRef.onDestroy(() => { 11 this.store.stopListeningToRealtimeDoggoEvents(); 12 }); 13 } 14 15 rateDoggo(rating: number): void { 16 this.store.rateDoggo(rating); 17 } 18 19 skipDoggo(): void { 20 this.store.selectNextDoggo(); 21 } 22 23 selectDoggo(id: string): void { 24 this.store.selectDoggo(id); 25 } 26 } 27 store = inject(DoggosStore); @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 doggoId = input(''); 3 4 private readonly destroyRef = inject(DestroyRef); 5 6 ngOnInit(): void { 7 this.store.loadDoggos(this.doggoId()); 8 this.store.startListeningToRealtimeDoggoEvents(); 9 10 this.destroyRef.onDestroy(() => { 11 this.store.stopListeningToRealtimeDoggoEvents(); 12 }); 13 } 14 15 rateDoggo(rating: number): void { 16 this.store.rateDoggo(rating); 17 } 18 19 skipDoggo(): void { 20 this.store.selectNextDoggo(); 21 } 22 23 selectDoggo(id: string): void { 24 this.store.selectDoggo(id); 25 } 26 } 27 ngOnInit(): void { this.store.loadDoggos(this.doggoId()); this.store.startListeningToRealtimeDoggoEvents(); this.destroyRef.onDestroy(() => { this.store.stopListeningToRealtimeDoggoEvents(); }); } @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 doggoId = input(''); 3 store = inject(DoggosStore); 4 private readonly destroyRef = inject(DestroyRef); 5 6 7 8 9 10 11 12 13 14 15 rateDoggo(rating: number): void { 16 this.store.rateDoggo(rating); 17 } 18 19 skipDoggo(): void { 20 this.store.selectNextDoggo(); 21 } 22 23 selectDoggo(id: string): void { 24 this.store.selectDoggo(id); 25 } 26 } 27 rateDoggo(rating: number): void { this.store.rateDoggo(rating); } skipDoggo(): void { this.store.selectNextDoggo(); } selectDoggo(id: string): void { this.store.selectDoggo(id); } } @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 doggoId = input(''); 3 store = inject(DoggosStore); 4 private readonly destroyRef = inject(DestroyRef); 5 6 ngOnInit(): void { 7 this.store.loadDoggos(this.doggoId()); 8 this.store.startListeningToRealtimeDoggoEvents(); 9 10 this.destroyRef.onDestroy(() => { 11 this.store.stopListeningToRealtimeDoggoEvents(); 12 }); 13 } 14 15 16 17 18 19 20 21 22 23 24 25 26 27
  7. @Component({ /* ... */ }) export class DoggoListComponent { doggos:

    = input<Doggos[]>([]); doggoSelected = output<string>(); selectDoggo(doggo: Doggo) { this.doggoSelected.emit(doggo.id); } } 1 2 3 4 5 6 7 8 9 10
  8. @Component({ /* ... */ }) export class DoggoListComponent { doggos:

    = input<Doggos[]>([]); doggoSelected = output<string>(); selectDoggo(doggo: Doggo) { this.doggoSelected.emit(doggo.id); } } 1 2 3 4 5 6 7 8 9 10 doggos: = input<Doggos[]>([]); @Component({ /* ... */ }) 1 export class DoggoListComponent { 2 3 4 doggoSelected = output<string>(); 5 6 selectDoggo(doggo: Doggo) { 7 this.doggoSelected.emit(doggo.id); 8 } 9 } 10
  9. @Component({ /* ... */ }) export class DoggoListComponent { doggos:

    = input<Doggos[]>([]); doggoSelected = output<string>(); selectDoggo(doggo: Doggo) { this.doggoSelected.emit(doggo.id); } } 1 2 3 4 5 6 7 8 9 10 doggos: = input<Doggos[]>([]); @Component({ /* ... */ }) 1 export class DoggoListComponent { 2 3 4 doggoSelected = output<string>(); 5 6 selectDoggo(doggo: Doggo) { 7 this.doggoSelected.emit(doggo.id); 8 } 9 } 10 doggoSelected = output<string>(); selectDoggo(doggo: Doggo) { this.doggoSelected.emit(doggo.id); } @Component({ /* ... */ }) 1 export class DoggoListComponent { 2 doggos: = input<Doggos[]>([]); 3 4 5 6 7 8 9 } 10
  10. Nx is built on a technology-agnostic core that maintains modular

    units of code and understands the dependency graph between them. "
  11. App About Doggos Container Container Ui Domain Utils Shared util-environments

    util-Auth util-Common UI-common scope:about scope:doggos scope:shared
  12. App About Doggos container container Ui Domain Utils type:container Shared

    util-environments util-Auth util-Common UI-common scope:about scope:doggos scope:shared
  13. App About Doggos Container Ui Domain Utils type:container type:ui type:domain

    type:utils Shared util-environments util-Auth util-Common UI-common scope:about scope:doggos scope:shared container type:container
  14. App About Doggos Ui Domain Utils type:ui type:domain type:utils Shared

    util-environments type:util util-Auth util-Common UI-common type:util type:util type:ui scope:about scope:doggos scope:shared Container type:container container type:container