Timing Your Angular 17 Upgrade

With Angular 18 slated for release around the week of May 20, 2024, the window for moving production applications to Angular 17 is now open.

Beyond the automated upgrade handled by the Angular CLI, you'll need to address third-party dependencies, run the control flow migration, and consider adopting the new application builder powered by esbuild and Vite.

When to Upgrade

My colleague Manfred and I typically advise upgrading after the first or second minor release, specifically V[N].1.0 or V[N].2.0, and before the next major version V[N+1].0.0 lands.

Holding off until the second minor release gives the ecosystem time to catch up. Third-party libraries often need a few weeks to ship compatible versions. Waiting ensures they've had the chance to test and stabilize their packages for production scenarios.

For Angular 17, that ideal window runs from V17.2.0 (released February 14, 2024) through V18.0.0 (expected the week of May 20, 2024). In other words, the time to act is now.

Executing the Angular Upgrade

Leveraging the Angular CLI

In practice, Angular upgrades are generally painless. The Angular CLI offers a robust automation tool for this process. To bring your project up to Angular 17, execute:

ng update @angular/core@17 @angular/cli@17

Based on your project's configuration, you may also need to include packages such as @angular/material, @angular/cdk, or @angular-eslint/schematics:

ng update @angular/core@17 @angular/cli@17 @angular/material@17 @angular/cdk@17 @angular-eslint/schematics@17

For projects using Nrwl's Nx, the equivalent command is:

nx migrate latest

These core Angular updates are typically very smooth. When changes are required in your source or configuration files, the CLI either implements them automatically or, if that's not feasible, provides clear guidance on the necessary steps.

Interestingly, the official roadmap includes plans to integrate AI into the Angular CLI to further streamline these automated updates.

Handling Third-Party Packages Manually

It's crucial to understand that the CLI does not handle every dependency. Given that most Angular applications rely on external libraries, you'll need to verify that each one offers a version compatible with Angular 17. Where compatible versions exist, update them. Even for non-Angular-specific libraries, staying current is important for new features, fixes, and—most critically—security patches. Whatever you do, be mindful of peer dependency conflicts.

Here's a typical manual update workflow. First, identify which packages have pending updates:

npm outdated

Next, update those packages. I usually rely on my IDE, IntelliJ WebStorm, for version discovery: open package.json and the editor will suggest the latest versions as you edit. Once you've updated the version numbers, install them with:

npm i | yarn | pnpm i

Key Considerations for Dependency Updates

  1. When using component libraries—from Bootstrap to Angular Material—pay close attention to breaking changes in their release notes.
  2. If you work on several front-end projects, consider pnpm. It offers much faster installs and dramatically reduces disk usage.
  3. Strive to prevent peer dependency conflicts. For example, the latest eslint (9.X.X) cannot be used with @angular-eslint, which currently supports only version 8.X.X. Until that changes (maybe in Version 18), you'd pin eslint to 8.57.0. In certain situations, you may have to resort to npm i --legacy-peer-deps, but be aware this can compromise your dependency tree—use it sparingly.
  4. When upgrading across multiple major versions, proceed incrementally. Upgrading one major version at a time and testing thoroughly between steps makes it much easier to isolate and resolve breaking changes. For instance, Angular 16 removed support for ViewEngine libraries, so all your dependencies must be Ivy-compatible beforehand. In some cases, you might need to swap out libraries that haven't caught up; I've had to do this in my own projects.

Assuming your project is now on Angular 17 and your dependencies are aligned (excluding those like eslint that are waiting on updates), we can proceed to the next migration.

Migrating to the New Control Flow

Angular 17 introduces a new control flow syntax for templates. The Angular team's goals were improved performance and a better developer experience. I'll admit, the initial look reminded me of PHP and felt a bit odd. However, it's surprisingly easy to adapt to. According to independent benchmarks, the runtime handling of @for loops can be up to 90% faster:

Angular 17 Control Flow Benchmarks

Executing the Migration Schematic

This migration isn't automatic. To convert your HTML templates to the new syntax, run this Angular CLI schematic:

ng g @angular/core:control-flow

Refining and Cleaning Up Manually

While the schematic usually works flawlessly—at least in my experience—you may want to refine the generated code manually for better quality and readability.

Here's some general guidance on using the new control flow:

  1. Review your @if blocks. Consider simplifying complex conditions by leveraging @else if and @else. This often makes templates more readable and maintainable.
  2. Inspect your @for blocks. Adding an @empty block can eliminate extra markup for empty states. Also, ensure you're using the now-required track parameter thoughtfully.
  3. Encourage adoption within your team. Add the relevant @angular-eslint rule to your eslint configuration to enforce the new syntax:
    "files": ["*.html"],
    "rules": {
     "@angular-eslint/template/prefer-control-flow": "warn",
  4. With the new control flow in place, consider introducing @defer blocks for heavy components to optimize initial loads.
  5. Leveraging @defer for Component Lazy-Loading

    For a deep dive into @defer, refer to my article on Angular 17’s Deferrable Views. It's particularly beneficial for large dependencies—see this guide on lazy-loading large third-party libraries.

    With templates migrated, we move to the final step.

    Switching to the Application Builder

    The new application builder, which debuted in Angular 16 and harnesses esbuild and Vite, became the default for new projects in Angular 17. If you haven't adopted it yet, now's the time. It's significantly faster, reportedly more reliable, and can produce marginally smaller bundles.

    To switch an existing app, you can either run an update script or manually edit angular.json (or project.json for Nx workspaces).

    Automated Builder Update

    Use this dedicated script to update all application builders automatically:

    ng update @angular/cli --name use-application-builder

    Manual Configuration in angular.json

    Your current angular.json likely contains a builder configuration similar to:

    "architect": {
      "build": {
        "builder": "@angular-devkit/build-angular:browser",

    The first modification is to change the builder field:

    "architect": {
      "build": {
        "builder": "@angular-devkit/build-angular:application",

    You'll also need to rename the main option to browser within the build target. The table below, sourced from the official Angular esbuild documentation, summarizes these changes:

    esbuild

    For applications using SSR, don't forget to update the builder in the server targets as well.

    Finding a webpack Bundle Analyzer Alternative

    Moving away from webpack means finding a replacement for webpack-bundle-analyzer. Here are some tools for analyzing your Vite-based bundles:

    • source-map-explorer (compatible with both webpack and Vite)
      npx source-map-explorer dist/[app-name]/browser/**/*.js --no-border-checks
    • vite-bundle-visualizer
      npx vite-bundle-visualizer -i dist/[app-name]/browser/index.html
    • Google Lighthouse DevTools offers a Treemap feature for source inspection—see the screenshot:
      Google Lighthouse Treemap

    If you have other tools you'd like to recommend or any feedback, feel free to reach out via email, X, or LinkedIn.

    Final Thoughts

    Angular 17 has matured significantly, so it's time to upgrade and migrate your projects.

    This post covered updating Angular and its third-party packages, migrating to the new control flow, and adopting the new application builder based on esbuild and Vite.

    References

    Workshops

    For those looking to go deeper, we provide a range of workshops available in both English and German.

    This post was authored by Alexander Thalhammer. Connect with me on Linkedin, X, or giThub.