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

Angular 17: Neue Features optimal nutzen und Bestandsprojekte effizient migrieren

Angular 17: Neue Features optimal nutzen und Bestandsprojekte effizient migrieren

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 größtenteils aus der Entwicklervorschau entlassen, Standalone-Komponenten und -APIs werden zum Standard und ersetzen NgModules, der neue Kontrolfluss (@if/@for) feiert sein Debüt gemeinsam mit den Deferrable Views und es gibt ein neues Buildsystem auf Basis von esbuild und Vite.
Christian Liebel stellt in diesem Webinar die Neuerungen in Angular 17 vor und gibt eine Einschätzung, ob, wann und wie Entwickler auf die neuen Features umsteigen sollen. Kommen Sie vorbei und bringen Sie Ihr Angular-Wissen auf den neusten Stand!

Christian Liebel

February 07, 2024
Tweet

More Decks by Christian Liebel

Other Decks in Programming

Transcript

  1. Hello, it’s me. Angular 17 Neue Features optimal nutzen und

    Bestandsprojekte effizient migrieren 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 Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren “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. Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren “Angular Renaissance”
  4. Signals Standalone Components and APIs Built-in Control Flow and Deferrable

    Views esbuild and Vite Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Agenda
  5. 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 Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Signals
  6. OLD Zone.js-based Change Detection Angular 17 Neue Features optimal nutzen

    und Bestandsprojekte effizient migrieren 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 }}
  7. POSSIBLE Future Change Detection Angular 17 Neue Features optimal nutzen

    und Bestandsprojekte effizient migrieren Signals CHANGE <app-root> <app-nav> <app-content> <app-list> {{ binding }} {{ signal() }} {{ binding }} {{ binding }}
  8. 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()}`)); Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Signals https://angular.dev/guide/signals
  9. 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() Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Signals https://angular.dev/guide/signals/rxjs-interop
  10. 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>(); } Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren 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 Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren 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) Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren 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.) Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Signals P
  14. Signals Standalone Components and APIs Built-in Control Flow and Deferrable

    Views esbuild and Vite Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Agenda
  15. Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren

    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
  16. @NgModule({ declarations: [AppComponent, HomeComponent, MenuComponent], imports: [BrowserModule], providers: [DataService], bootstrap:

    [AppComponent], }) export class AppModule { } Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren NgModules
  17. 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? Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren NgModules OLD
  18. @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[]; } Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Standalone Components NEW
  19. Lazy Loading export const ROUTES: Route[] = [ { path:

    'admin', loadComponent: () => import('./admin/panel.component') .then(mod => mod.AdminPanelComponent), providers: [MyService] }, // … ]; Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Standalone Components https://angular.io/guide/standalone-components#lazy-loading-a-standalone-component
  20. 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[]; Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Standalone Components https://angular.io/guide/standalone-components#lazy-loading-many-routes-at-once
  21. “Modules” export const CAROUSEL_DIRECTIVES = [ ImageCarouselComponent, ImageSlideComponent ] as

    const; @Component({ standalone: true, imports: [CAROUSEL_DIRECTIVES] }) export class MyComponent {} Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Standalone Components https://angular.dev/guide/standalone-components#standalone-components-for-library-authors
  22. 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 {} Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Standalone Components
  23. 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[]; } Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Standalone Components
  24. 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 Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Standalone Components
  25. 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); Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Standalone Components
  26. 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 Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Standalone Applications OLD NEW
  27. 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)); Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Standalone Applications OLD NEW
  28. Providers Modules @NgModule({ imports: [ BrowserModule, RouterModule.forRoot(routes), HttpClientModule ] })

    export class AppModule { } Standalone Apps export const appConfig: ApplicationConfig = { providers: [ provideRouter(routes), provideHttpClient(), // fallback for modules: importProvidersFrom (TranslateModule) ] }; Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Standalone Applications OLD NEW
  29. Environment Injectors Modules @NgModule({ providers: [{ provide: PhotosService, useClass: CustomPhotosService,

    }] }) export class MyModule { constructor() { // My logic } } Standalone Apps createEnvironmentInjector([ { provide: PhotosService, useClass: CustomPhotosService }, { provide: ENVIRONMENT_INITIALIZER, useValue: () => {/* My logic */} } ]); Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Standalone Applications OLD NEW
  30. 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. Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Standalone Components & APIs
  31. 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) Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Standalone Components & APIs
  32. Migration ng g @angular/core:standalone Angular 17 Neue Features optimal nutzen

    und Bestandsprojekte effizient migrieren Standalone Components & APIs
  33. 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 Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Standalone Components & APIs https://angular.io/guide/standalone-migration#migrations-steps
  34. Signals Standalone Components and APIs Built-in Control Flow and Deferrable

    Views esbuild and Vite Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Agenda
  35. If <ng-container *ngIf="item; else notFound"> <app-component [item]="item" /> </ng-container> <ng-template

    #notFound> Item not found! </ng-template> @if (item) { <app-component [item]="item" /> } @else { Item not found! } Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Built-in Control Flow OLD NEW https://angular.dev/essentials/conditionals-and-loops#if-block
  36. Motivation – Control flow is built into the renderer, so

    you don’t have to import the structural directives (e.g., CommonModule, NgIf). – Dummy DOM elements such as <ng-container> are no longer needed. – The structural directive syntax (e.g., *ngIf) is not very common. – Better performance (up to 90% for @for), no longer tied to Zone.js. – Improve developer experience when dealing with common scenarios, such as “else” blocks, empty lists or deferring loading certain content. – ⚠ But: Built-in control flow is not extensible, in contrast to structural directives (e.g., *ngxPermission). Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Built-in Control Flow https://angular.dev/guide/templates/control-flow https://blog.angular.io/introducing-angular-v17-4d7033312e4b
  37. Switch <ng-container [ngSwitch]="condition"> <ng-container *ngSwitchCase="caseA"> Case A. </ng-container> <ng-container *ngSwitchDefault>

    Default case. </ng-container> </ng-container> @switch (condition) { @case (caseA) { Case A. } @default { Default case. } } Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Built-in Control Flow OLD NEW https://angular.dev/guide/templates/control-flow#switch-block---selection
  38. For <li *ngFor="let item of items; trackBy: trackByFn"> {{ item.name

    }} </li> <li *ngIf="items.length===0"> No items. </li> @for (item of items; track item.name) { <li> {{ item.name }} </li> } @empty { <li> No items. </li> } Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Built-in Control Flow OLD NEW https://angular.dev/essentials/conditionals-and-loops#for-block
  39. Migration Strategy – Maturity: The built-in control flow is in

    developer preview. – Why? Optimizes developer experience for common scenarios and improves performance (Zone.js, mandatory tracking in for loops) – When? Changes are still possible as the feature is in developer preview. If you can handle potential changes, start using control flow now and migrate your codebase as soon as possible. Otherwise, keep using structural directives and migrate later. – Supported by current versions of WebStorm, VS Code and Prettier. – ⚠ But: The syntax does not match the HTML standard and may lead to problems with older IDE versions or tooling that is not aware of it. Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Built-in Control Flow
  40. How? – Migration can be automated – Target path can

    be specified (allowing a step-by-step migration) – Allows formatting affected files – Removes CommonModule/structural directive imports from component class – Manual changes likely required – Effort for mid-size projects: < 1 hour – No functional changes Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Built-in Control Flow
  41. How? – ⚠ Migration is in developer preview itself –

    ⚠ @for tracks the count variable by default (not necessarily the best performance) – ⚠ The built-in control flow does not support some rarely used features that were previously possible (e.g., *ngFor collection aliasing, multiple *ngIf aliases, …). These usages must be changed before running the migration. – ⚠ Template reformatting does not use Prettier Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Built-in Control Flow
  42. Migration ng g @angular/core:control-flow Angular 17 Neue Features optimal nutzen

    und Bestandsprojekte effizient migrieren Built-in Control Flow
  43. Motivation – Takes lazy loading a step further by bringing

    it to the template level, which can improve the load time performance of your application. – Loads a (large/rarely used) view only based on a certain trigger (e.g., when the template enters the viewport, the device is idle, …). – Everything uses template magic, enabled by the new @defer block. – Offers helpers like @placeholder (while the content is being loaded), or @error when the content fails to load. – An example for a feature that is only accessible via the new syntax. Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Deferrable Views
  44. Examples @defer (on viewport) { <calendar-cmp /> } @placeholder {

    <div>Calendar placeholder</div> } @error { Failed to load the calendar! } Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Deferrable Views https://angular.dev/guide/defer
  45. Signals Standalone Components and APIs Built-in Control Flow and Deferrable

    Views esbuild and Vite Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Agenda
  46. Motivation The JavaScript ecosystem has advanced and new (and significantly

    faster) build tools have arrived. Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren esbuild and Vite https://esbuild.github.io/
  47. 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) Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren esbuild and Vite https://blog.angular.io/introducing-angular-v17-4d7033312e4b
  48. 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", Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren esbuild and Vite https://angular.io/guide/esbuild NEW
  49. 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. Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren esbuild and Vite
  50. 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. Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren esbuild and Vite
  51. Migration ng update @angular/cli --name use-application-builder Angular 17 Neue Features

    optimal nutzen und Bestandsprojekte effizient migrieren esbuild and Vite
  52. Feature Maturity Benefit Criticality Effort Signals ••◦ ••◦ •◦◦ •••

    Standalone ••• ••◦ ••◦ ••◦ Control Flow •◦◦ •◦◦ •◦◦ •◦◦ esbuild and Vite ••• ••• ••• ••◦ Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Summary
  53. 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 Angular 17 Neue Features optimal nutzen und Bestandsprojekte effizient migrieren Summary P