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. Angular 17
    Neue Features optimal nutzen und
    Bestandsprojekte effizient migrieren
    Christian Liebel
    @christianliebel
    Consultant

    View full-size slide

  2. 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

    View full-size slide

  3. Angular 17
    Neue Features optimal nutzen und Bestandsprojekte effizient migrieren
    “Angular Renaissance” P

    View full-size slide

  4. 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”

    View full-size slide

  5. 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”

    View full-size slide

  6. 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

    View full-size slide

  7. 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

    View full-size slide

  8. 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



    CHANGE
    {{ binding }}
    {{ binding }} {{ binding }}
    {{ binding }}

    View full-size slide

  9. POSSIBLE Future Change Detection
    Angular 17
    Neue Features optimal nutzen und Bestandsprojekte effizient migrieren
    Signals
    CHANGE



    {{ binding }}
    {{ signal() }} {{ binding }}
    {{ binding }}

    View full-size slide

  10. 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

    View full-size slide

  11. 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

    View full-size slide

  12. 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();
    }
    Angular 17
    Neue Features optimal nutzen und Bestandsprojekte effizient migrieren
    Signals
    https://blog.angular-university.io/angular-signal-inputs/
    OLD NEW

    View full-size slide

  13. 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

    View full-size slide

  14. 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

    View full-size slide

  15. 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

    View full-size slide

  16. 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

    View full-size slide

  17. 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

    View full-size slide

  18. @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

    View full-size slide

  19. The problem with modules…
    @Component({
    selector: 'app-my',
    template: `[appTooltip]="item.tooltip">{{ item.name | myPipe }}`,
    })
    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

    View full-size slide

  20. @Component({
    selector: 'app-my',
    template: `[appTooltip]="item.tooltip">{{ item.name | myPipe }}`,
    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

    View full-size slide

  21. 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

    View full-size slide

  22. 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

    View full-size slide

  23. “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

    View full-size slide

  24. 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

    View full-size slide

  25. Interoperability with NgModules
    @Component({
    selector: 'app-my',
    template: `[appTooltip]="item.tooltip">{{ item.name | myPipe }}`,
    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

    View full-size slide

  26. 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

    View full-size slide

  27. 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

    View full-size slide

  28. Angular 17
    Neue Features optimal nutzen und Bestandsprojekte effizient migrieren

    View full-size slide

  29. 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

    View full-size slide

  30. 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

    View full-size slide

  31. 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

    View full-size slide

  32. 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

    View full-size slide

  33. 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

    View full-size slide

  34. 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

    View full-size slide

  35. Migration
    ng g @angular/core:standalone
    Angular 17
    Neue Features optimal nutzen und Bestandsprojekte effizient migrieren
    Standalone Components & APIs

    View full-size slide

  36. 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

    View full-size slide

  37. 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

    View full-size slide

  38. If
    *ngIf="item; else notFound">
    [item]="item" />


    Item not found!

    @if (item) {
    [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

    View full-size slide

  39. 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 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

    View full-size slide

  40. Switch
    [ngSwitch]="condition">
    *ngSwitchCase="caseA">
    Case A.

    *ngSwitchDefault>
    Default case.


    @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

    View full-size slide

  41. For
    items; trackBy: trackByFn">
    {{ item.name }}


    No items.

    @for (item of items;
    track item.name) {
    {{ item.name }}
    } @empty {
    No items.
    }
    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

    View full-size slide

  42. 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

    View full-size slide

  43. 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

    View full-size slide

  44. 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

    View full-size slide

  45. Migration
    ng g @angular/core:control-flow
    Angular 17
    Neue Features optimal nutzen und Bestandsprojekte effizient migrieren
    Built-in Control Flow

    View full-size slide

  46. 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

    View full-size slide

  47. Examples
    @defer (on viewport) {

    } @placeholder {
    Calendar placeholder
    } @error {
    Failed to load the calendar!
    }
    Angular 17
    Neue Features optimal nutzen und Bestandsprojekte effizient migrieren
    Deferrable Views
    https://angular.dev/guide/defer

    View full-size slide

  48. 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

    View full-size slide

  49. 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/

    View full-size slide

  50. 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

    View full-size slide

  51. 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

    View full-size slide

  52. 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

    View full-size slide

  53. 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

    View full-size slide

  54. Migration
    ng update @angular/cli --name use-application-builder
    Angular 17
    Neue Features optimal nutzen und Bestandsprojekte effizient migrieren
    esbuild and Vite

    View full-size slide

  55. Feature Maturity Benefit Criticality Effort
    Signals ●●○ ●●○ ●○○ ●●●
    Standalone ●●● ●●○ ●●○ ●●○
    Control Flow ●○○ ●○○ ●○○ ●○○
    esbuild and Vite ●●● ●●● ●●● ●●○
    Angular 17
    Neue Features optimal nutzen und Bestandsprojekte effizient migrieren
    Summary

    View full-size slide

  56. 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

    View full-size slide

  57. Thank you
    for your kind attention!
    Christian Liebel
    @christianliebel
    [email protected]

    View full-size slide