Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Signals, Standalone, SSR: So bauen Sie Angular-...

Signals, Standalone, SSR: So bauen Sie Angular-Apps der Zukunft

Es ist die Wiedergeburt von Angular: Mit keinem geringeren Begriff untertitelt das Angular-Team die Veröffentlichung der 17. Hauptversion des SPA-Frameworks.
Recht hat das Angular-Team, denn die Gestalt von Angular-Apps wird sich in Zukunft nachhaltig verändern: In dieser Fassung wird der neue reaktive Basisdatentyp Signals aus der Entwicklervorschau entlassen, Standalone-Komponenten und -APIs werden zum Standard und das Server-Side Rendering für eine verbesserte Ladezeitperformance wurde deutlich aufgebohrt.
Christian Liebel von Thinktecture stellt die Neuerungen in Angular 17 vor und gibt eine Einschätzung, wie Entwickler auf die neuen Features umsteigen sollen. Kommen Sie vorbei und bringen Sie Ihr Angular-Wissen auf den neusten Stand!

Christian Liebel

February 14, 2024
Tweet

More Decks by Christian Liebel

Other Decks in Programming

Transcript

  1. Hello, it’s me. Signals, Standalone, SSR So bauen Sie Angular-Apps

    der Zukunft Christian Liebel X: @christianliebel Email: christian.liebel @thinktecture.com Angular & PWA Slides: thinktecture.com /christian-liebel
  2. Angular 16+ – Signals, Signal-based inputs (…and a Zone.js-less future)

    – Standalone Components/APIs – Built-in Control Flow/Deferrable Views – New build tools: esbuild & Vite – Server-Side Rendering/Hydration Goals: Streamline & modernize APIs & improve performance Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft “Angular Renaissance”
  3. Angular 16+ But: The shape of Angular apps changes significantly.

    You can tell the difference between an Angular 2 and an Angular 17 app. No worries: All new features are backwards compatible & interoperable. Not another AngularJS scenario. Still: You should migrate your applications as soon as possible. In this session, we talk about why, when and how you should migrate. Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft “Angular Renaissance”
  4. Overview – A signal is a reactive primitive: a wrapper

    around a value that notifies interested consumers when that value changes – The signal concept is a lot simpler than RxJS (= streamlined APIs) – Signals form the basis for a new, more effective change detection system in Angular that could eventually replace Zone.js (= performance improvement) – Works great with ChangeDetectionStrategy.OnPush Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Signals
  5. OLD Zone.js-based Change Detection Signals, Standalone, SSR So bauen Sie

    Angular-Apps der Zukunft Signals current (global) zone NgZone Angular boot onclick setTimeout Detect changes Detect changes <app-root> <app-nav> <app-content> <app-list> CHANGE {{ binding }} {{ binding }} {{ binding }} {{ binding }}
  6. POSSIBLE Future Change Detection Signals, Standalone, SSR So bauen Sie

    Angular-Apps der Zukunft Signals CHANGE <app-root> <app-nav> <app-content> <app-list> {{ binding }} {{ signal() }} {{ binding }} {{ binding }}
  7. API – Writable Signals const count = signal(0); count.set(3); –

    Computed Signals const doubleCount = computed(() => count() * 2); – Effects effect(() => console.log(`The count is: ${doubleCount()}`)); Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Signals https://angular.dev/guide/signals
  8. RxJS Interop – Convert observable to signal counter$ = interval(1000);

    counter = toSignal(this.counter$, {initialValue: 0}); – Convert signal to observable counter = signal(0); counter$ = toObservable(this.counter); – takeUntilDestroyed() Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Signals https://angular.dev/guide/signals/rxjs-interop
  9. Signal-based Components (since Angular 17.1) @Component({ selector: "counter", standalone: true,

    template: "{{ value }}", }) export class CounterComponent { @Input() value = 0; @Input({ required: true }) value2!: number; } @Component({ selector: "counter", standalone: true, template: "{{ value() }}", }) export class CounterComponent { value = input(0); value2 = input.required<number>(); } Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Signals https://blog.angular-university.io/angular-signal-inputs/ OLD NEW
  10. Signal-based Components (Angular 17.2 RC) @Component({ selector: "my-input", standalone: true,

    template: "{{ value }}", }) export class CounterComponent { @Input({ required: true }) value = 0; @Output() valueChange = new EventEmitter<number>(); } @Component({ selector: "my-input", standalone: true, template: "{{ value() }}", }) export class CounterComponent { value = model.required<number>(); } Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Signals https://blog.angular-university.io/angular-signal-inputs/ OLD NEW
  11. NgRx Signal Store – Reactive state management solution based on

    Signals – Simple and lightweight – Package: @ngrx/signals – Can be used globally and locally – Replacement for NgRx store, component store and entity adapter – Function-based, but can be class-based Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Signals https://ngrx.io/guide/signals
  12. Maturity – effect(), RxJS interop and signal-based components are still

    in developer preview (as of Angular 17.1.2) – @ngrx/signals is still in developer preview (as of version 17.1.0) Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Signals
  13. Migration Strategy – Why? You should migrate to Signals, as

    they improve performance and API simplicity. – When? You should write new components based on Signals and migrate older components if time permits. Currently, there’s no hurry: RxJS and the traditional ways in Angular won’t go away anytime soon, and some Signal APIs and frameworks are still in developer preview. – How? Manual effort required, no automated migration available. (Could probably be handled by GenAI.) Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Signals
  14. Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft NgModules

    UI-related components (BookModule) UI-related components (TodoModule) Logic/ infrastructure components (BookModule) Logic/ infrastructure components (TodoModule) Components Directives Pipes High-Level Services Low-Level Services
  15. @NgModule({ declarations: [AppComponent, HomeComponent, MenuComponent], imports: [BrowserModule], providers: [DataService], bootstrap:

    [AppComponent], }) export class AppModule { } Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft NgModules
  16. The problem with modules… @Component({ selector: 'app-my', template: `<a *ngFor="let

    item of items" [appTooltip]="item.tooltip">{{ item.name | myPipe }}</a>`, }) export class MyComponent { @Input({ required: true }) items!: Item[]; } Question: Where does appTooltip and myPipe come from? Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft NgModules OLD
  17. @Component({ selector: 'app-my', template: `<a *ngFor="let item of items" [appTooltip]="item.tooltip">{{

    item.name | myPipe }}</a>`, standalone: true, imports: [NgFor, TooltipDirective, MyPipe] }) export class MyComponent { @Input({ required: true }) items!: Item[]; } Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Standalone Components NEW
  18. Lazy Loading export const ROUTES: Route[] = [ { path:

    'admin', loadComponent: () => import('./admin/panel.component') .then(mod => mod.AdminPanelComponent), providers: [MyService] }, // … ]; Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Standalone Components https://angular.io/guide/standalone-components#lazy-loading-a-standalone-component
  19. Lazy Loading Multiple Routes export const ROUTES: Route[] = [

    {path: 'admin', loadChildren: () => import('./admin/routes')}, // … ]; export default [ {path: 'home', component: AdminHomeComponent}, {path: 'users', component: AdminUsersComponent}, // … ] as Route[]; Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Standalone Components https://angular.io/guide/standalone-components#lazy-loading-many-routes-at-once
  20. “Modules” export const CAROUSEL_DIRECTIVES = [ ImageCarouselComponent, ImageSlideComponent ] as

    const; @Component({ standalone: true, imports: [CAROUSEL_DIRECTIVES] }) export class MyComponent {} Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Standalone Components https://angular.dev/guide/standalone-components#standalone-components-for-library-authors
  21. Interoperability with NgModules – Standalone components/directives/pipes can’t be part of

    NgModules – When used in non-standalone components, it needs to be imported @NgModule({ declarations: [MyStandaloneComponent], imports: [MyStandaloneComponent], }) export const MyModule {} Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Standalone Components
  22. Interoperability with NgModules @Component({ selector: 'app-my', template: `<a *ngFor="let item

    of items" [appTooltip]="item.tooltip">{{ item.name | myPipe }}</a>`, standalone: true, imports: [CommonModule, TooltipModule, PipeModule] }) export class MyComponent { @Input({ required: true }) items!: Item[]; } Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Standalone Components
  23. Web Components Streamlined standalone API simplifies the creation of web

    components from Angular components Web components can be used in any context (not only Angular apps) ⚠ Problem: Zone.js is still used for change detection, should become less relevant in the future with signals Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Standalone Components
  24. Angular Elements import { createCustomElement } from '@angular/elements'; import {

    createApplication } from '@angular/platform-browser'; import { MyComponent } from './app/my/my.component'; const {injector} = await createApplication({ providers: [/* add providers */] }); const myElement = createCustomElement(MyComponent, { injector }); customElements.define('my-element', myElement); Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Standalone Components
  25. Folder Structure Modules main.ts app/app-routing.module.ts app/app.module.ts Standalone Apps main.ts app/app.routes.ts

    app/app.config.ts Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Standalone Applications OLD NEW
  26. Bootstrap API Modules import { platformBrowser } from '@angular/platform-browser'; import

    { AppModule } from './app/app.module'; platformBrowser() .bootstrapModule(AppModule) .catch(e => console.error(e)); Standalone Apps import { bootstrapApplication } from '@angular/platform-browser'; import { AppComponent } from './app/app.component'; bootstrapApplication(AppComponent) .catch(e => console.error(e)); Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Standalone Applications OLD NEW
  27. Migration Strategy – Maturity: Standalone components and APIs are fully

    stable. – Why? Standalone components and APIs improve developer experience and prepare your codebase for upcoming Angular features. – When? New projects should be started using standalone APIs, new components should be added as standalone components (default since version 17), NgModules and standalone are interoperable. – Existing projects should be migrated as soon as possible, new parts should be added using standalone components/APIs. – ⚠ Some ng add/ng update integrations may not work with standalone workspaces. Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Standalone Components & APIs
  28. How? – Migration can be partly automated – Manual changes

    will be required – Effort for mid-size projects: 4–8 hours – No functional difference – ⚠ Changes to the project setup may lead to the migration to break – ⚠ Replacements in unit tests may be incorrect – ⚠ Migration does not introduce the new folder structure (app config) Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Standalone Components & APIs
  29. Migration ng g @angular/core:standalone Signals, Standalone, SSR So bauen Sie

    Angular-Apps der Zukunft Standalone Components & APIs
  30. Migration 1. Run ng g @angular/core:standalone and select "Convert all

    components, directives and pipes to standalone" 2. Run ng g @angular/core:standalone and select "Remove unnecessary NgModule classes" 3. Run ng g @angular/core:standalone and select "Bootstrap the project using standalone APIs" 4. Run any linting and formatting checks, fix any failures, and commit the result Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Standalone Components & APIs https://angular.io/guide/standalone-migration#migrations-steps
  31. Motivation – Server-side rendering (SSR) renders the application on the

    server, significantly improving load time performance – Prerendering/static site generation (SSG) renders all static HTML files during build time, improving server response time – Hydration allows client-side Angular to reattach to the server- rendered DOM nodes during launch, improving client-side load time Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Server-Side Rendering
  32. Motivation <html> <body> <app-root></app-root> </body> </html> <html> <body> <app-root _nghost-ng-c1888335296=""

    ng- version="17.1.3" ngh="0" ng-server- context="ssr"><main _ngcontent-ng- c1888335296="" class="main"><div _ngcontent- ng-c1888335296="" class="content"><div _ngcontent-ng-c1888335296="" class="left- side"><svg _ngcontent-ng-c1888335296="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 982 239" fill="none" class="angular-logo"><!-- -- ></svg></a></div></div></div></main><router- outlet _ngcontent-ng- c1888335296=""></router-outlet><!-- container--></app-root> </body> </html> Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Server-Side Rendering No SSR SSR
  33. In Angular 17 – SSR is now fully integrated with

    Angular and includes SSR, prerendering, and hydration – Angular Universal is no longer offered as a separate library – For new projects, SSR can be easily enabled (e.g., ng new <name> -- ssr) – Existing projects first have to switch to the new application builder and update their configuration Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Server-Side Rendering
  34. Caveats – ⚠ Setting up SSR with authentication is hard,

    SSG may be impossible. – ⚠ Custom or Noop Zone.js are not yet supported. – ⚠ Angular i18n with hydration is not yet supported. – ⚠ When the Angular Service Worker is used, SSR is only used on the first visit. – ⚠ All components must be built for hydration. – ⚠ Libraries that depend on DOM manipulation (D3 charts, grids, …) may break hydration. Skipping hydration is possible via ngSkipHydration, but you’ll lose the advantages of hydration. Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Server-Side Rendering
  35. Motivation The JavaScript ecosystem has advanced and new (and significantly

    faster) build tools have arrived. Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft esbuild and Vite https://esbuild.github.io/
  36. Motivation – Significantly faster build times (initial/incremental) – Compatibility with

    native ECMAScript Modules (ESM) and the modern JavaScript ecosystem – Hot module replacement (HMR) support for styles (performance improvement) Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft esbuild and Vite https://blog.angular.io/introducing-angular-v17-4d7033312e4b
  37. New Builders browser-esbuild More compatible, drop-in replacement for “browser” builder

    application Integrated SSR, requires code changes when SSR was used, requires configuration changes "architect": { "build": { "builder": "@angular-devkit/build-angular:application", "options": { "outputPath": { "base": "dist/my-app" }, "index": "src/index.html", "polyfills": [ "zone.js" ], "tsConfig": "tsconfig.app.json", "assets": [ "src/favicon.ico", "src/assets", Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft esbuild and Vite https://angular.io/guide/esbuild NEW
  38. Motivation – Maturity: New apps created in Angular 17 will

    automatically use the application builder – Why? Significantly faster build times, modern JavaScript – When? The existing Webpack-based build system is still stable. Old apps will not be migrated automatically. As Angular will move on, you should migrate as time permits. – How? Aim for application, if that is not possible, try browser-esbuild. Just replace the builders in angular.json and see if the build works. If not, investigate and estimate the effort. Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft esbuild and Vite
  39. Migration – ⚠ Output folders change, build pipelines may have

    to be adjusted. – ⚠ Manual changes may be required, depending on the dependencies. – ⚠ The effort may be very high for larger projects. – ⚠ Migration might not be possible due to incompatible dependencies. Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft esbuild and Vite
  40. Feature Maturity Benefit Criticality Effort Signals ••◦ ••◦ •◦◦ •••

    Standalone ••• ••◦ ••◦ ••◦ esbuild and Vite ••• ••• ••• ••◦ SSR ••• ••◦ •◦◦ ••• Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Summary
  41. The “Angular Renaissance” is real Notable advancements while being backwards

    compatible Increased build/runtime performance and developer experience Keep your users and developers happy Angular 17.1+ apps will look significantly different to previous versions Avoid technical debt, migrate now Signals, Standalone, SSR So bauen Sie Angular-Apps der Zukunft Summary