Angular 17 Update: Control Flow & App Builder Migration

Since Angular 18 is around the corner (planned for the Week of May 20, 2024), it's now time to actually update to Angular 17 in production.

Besides the automatic update process executed mainly by Angular's fantastic CLI, we also need to take care of 3rd party dependencies, the new control flow migration and eventually switch to the new application builder using esbuild and Vite.

When to update Angular

I generally recommend updating after the first or the second minor release V[N].2.0 and before the next major release V[N+1].0.0.

The reason for waiting up to the second minor is mainly to allow 3rd party libraries to catch up and provide compatible versions of their packages. Most of them will try to catch up earlier – however, just to make sure everything is well tested and stable for production use.

In case of the Angular 17 update, the recommended update window is between V17.2.0 (February 14, 2024) and V18.0.0 (planned for the week of May 20, 2024). So, it's about time to update 😊

Doing an Angular update

Using the Angular CLI

In my experience, Angular updates are usually quite smooth and straightforward. The Angular CLI provides a fantastic tool to automate the update process. You can run the following command to update your project to Angular 17:

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

Depending on your project setup, you might want to include some additional packages like code>@angular/material and code>@angular/cdk or code>@angular-eslint/schematics:

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

If you're using Nrwl Nx, you can simply run:

nx migrate latest

As already mentioned, these Angular core updates typically are very smooth. If something needs to be changed in your codebase or configuration, the CLI will do it automatically or – if that's not possible – tell you what to do and provide you with the necessary information.

By the way, it's officially planned to use AI in the Angular CLI in the future to make the automated update process even smoother 🀯

Manually updating 3rd party packages

However, you need to be aware that the CLI can't and doesn't update everything. Since most Angular Apps use 3rd party dependencies, you need to check if they have a compatible version for Angular 17. If yes, you must update them too. If they are not Angular specific you should update them as well to get the latest features, bug fixes and - most importantly - security updates. In any case, you should avoid peer dependency conflicts.

Here is an example of how you can update packages manually. First, check for outstanding updates:

npm outdated

Then update the mentioned packages. I typically use my favorite IDE, Intellij WebStorm, to find the latest version: Simply open your package.json and your IDE will show you the latest version of the package when editing the version. When done updating the dependencies, run:

npm i | yarn | pnpm i

Important notes on updating 3rd party packages

  1. If you're using Component Frameworks from Bootstrap to Angular Material, watch out for breaking changes that need your attention.
  2. If you're running multiple frontend projects on your machine, make sure to try pnpm for faster installs and much, much less disk space consumption πŸŽ‰
  3. Make sure to avoid peer dependency conflicts as good as possible. For example, you won't be able to use the latest eslint version 9.X.X because @angular-eslint currently only supports version 8.X.X. So you'd currently prefer eslint version 8.57.0 until @angular-eslint catches up (probably in Version 18, but who knows). In some cases however, we will have to use npm i --legacy-peer-deps and with that potentially screw up our dependency resolution – so be careful with that!
  4. Final advice on doing an update across multiple Angular versions: Do one version after the other and test everything in between. This way you can easily identify potential breaking changes and fix them step by step. For example, Angular 16 has dropped support for ViewEngine libraries, so you need to make sure that all your dependencies are already supporting Ivy. If not, you need to update them first. In some rare cases, you might even need to replace those dependencies. At least that's what I did in my projects.

Now let's assume you've successfully updated your project to Angular 17 and all your 3rd party dependencies (except the ones like eslint) are as well up-to-date. Let's move on to the next migration step.

New control flow migration

Angular 17 ships with its new template control flow syntax. The Angular team wanted to improve the framework performance and also the developer experience. At first glance the new syntax looked a bit awkward (like PHP) to me, I must confess. However, you'll get used to it pretty fast. The handling of code>@for loops during runtime is up to 90% faster according to independent benchmarks:

Angular 17 Control Flow Benchmarks

Running the migration schematic

The Angular CLI doesn't automatically migrate your project. To migrate your Angular HTML templates to the new control flow syntax, you can use this Angular CLI schematic:

ng g @angular/core:control-flow

Manual improvements & clean up

While the migration schematic hopefully (and in my experience actually) doesn't produce any errors or bugs, you might want to improve and clean up your code manually afterward.

Here is some general advice on the new control flow:

  1. Check your @if blocks. You might want to reduce complexity here and there by using the @else if and @else. This will make your HTML templates more readable and thus more maintainable.
  2. Check your @for blocks. You might want to add the @empty block – again cleaning up your HTML templates. Also, make sure you're using the now mandatory track intelligently.
  3. Enforce the new control flow syntax in your team. You might want to add the corresponding @angular-eslint rule to your eslint configuration:
    "files": ["*.html"],
    "rules": {
     "@angular-eslint/template/prefer-control-flow": "warn",
  4. Since you're now using the new control flow syntax, think about introducing @defer blocks for heavyweight components in your app.

Adding @defer for lazy-loading of components

To learn how to use code>@defer, check out my blog post Angular 17’s Deferrable Views. Make sure to use code>@defer especially for large dependencies: How to lazy load large 3rd-party deps with Angular 17’s @defer.

Now let's assume you've successfully migrated your HTML templates. Let's move on to the final migration step.

Application builder migration

Angular 16 introduced the new application builder – using modern tools esbuild and Vite – which has now become the default builder for new projects in Angular 17. If you haven't switched to the new builder yet, you should try it now. It is definitely faster and also said-to-be more reliable than the old one, and it even results in a slightly smaller build size 😎

To switch existing Angular apps to the new builder, you need to run the update script or edit your angular.json (or project.json for Nx projects).

Changing the app builders automatically

Run this special update script to update all app builders automatically:

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

Changing the app builder in angular.json

In your angular.json, you would typically find:

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

Changing the builder field is the first change you will need to make:

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

Additionally, you need to rename main to browser within the build target. Here is a table of changes copied from the Angular Docs on esbuild:

esbuild

If you're using SSR make sure to change the builder in the server targets as well.

Replacing webpack bundle analyzer

Since were not using webpack anymore, you need to replace the webpack-bundle-analyzer as well. Here are some tools you can use to analyze your Vite bundles:

  • source-map-explorer (works 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
  • To find the source Treemap feature of Google Lighthouse DevTools, look at this screenshot:
    Google Lighthouse Treemap

Please feel very free to contact me via email, X or LinkedIn if you have any other tool you'd like to recommend (and have it mentioned here) or if you have any other question or feedback concerning this blog post.

Conclusion

Angular 17 is already pretty stable, so it's time to update and migrate your Angular projects today.

In this post, we've shown you how to update Angular including 3rd-party packages and how to migrate to the new control flow and the new application builder using esbuild and Vite.

References

Workshops

If you want to deep dive into Angular, we offer a variety of workshops - both in English and German.

This blog post was written by Alex Thalhammer. Follow me on GitHub, X or LinkedIn.

eBook: Angular Standalone Components and APIs

Anhand von vielen Beispielen zeigt dieses kostenlose eBook in mehreren Kapiteln, wie man Standalone-Komponenten verwendet und wie sie bestehende APIs — z. B. den Router, Lazy Loading und NGRX — beeinflussen.

Gratis downloaden