Angular 20 is out. Nothing felt like a single dramatic breakβdevelopment continues as before. For specifics, see:
https://blog.angular.dev/announcing-angular-v20-b5c9c06cf301 Watch this video on YouTube
I'll leave developer-facing and technical deep dives to those sources. Here I share topics I found interesting while updating.
control-flow-migration
Running ng update surfaced this optional migration. I always think: they call it "optional," but with no ignore option and unknown follow-on migrations, it does not feel very optional. π
** Optional migrations of package '@angular/core' **
This package has 1 optional migration that can be executed.
Optional migrations may be skipped and executed after the update process, if preferred.
Select the migrations that you'd like to run (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to proceed)
β―β― [control-flow-migration] Converts the entire application to block control flow syntax.
After this, Angular 20+ projects effectively leave behind NgIf, NgFor, NgSwitch, and the old syntax. Those APIs are deprecated and will be removed in v22 about a year from now. Personally, watching a certain OSS project claim "backward compatibility" while APIs pile up into debt makes me appreciate Angular's cycle:
- Ship new replacement APIs
- Hear from the community
- Remove old APIs from user projects via automated migrations
- Mark deprecated
- Delete from the framework a year later and pay down debt
I love that turnover. It sits opposite the "it's mature so it's fine" crowd, but following along improves your projectβthat feels like a real framework.
Builder moves from @angular-devkit/build-angular to @angular/build
Tracing back, the first @angular/build commit is here:
https://github.com/angular/angular-cli/commit/810d213e1813dd01620173f5f999dca7bccf8ea1
@angular-devkit/build-angular stays Webpack-based with backward compatibility; @angular/build is esbuild/Vite only. Looking at @angular-devkit/build-angular's package.json, @angular/build is in dependencies, so @angular-devkit/build-angular becomes the compatibility layer.
If you have kept migrating with Angular, v19 already defaulted to esbuild (@angular-devkit/build-angular:application), so this is mostly a non-issue. One edge case: if you configure the test runner in karma.config.js with @angular-devkit/build-angular/plugins/karma, that plugin does not exist on @angular/buildβyou still need @angular-devkit/build-angular alongside it.
Roughly: the builder became a lighter package without backward-compat baggage.
Library output no longer includes source-mirror .d.ts files
Through Angular 19, library output (dist) kept type definition files mirroring the project structure alongside built artifacts. Example output for my scroll-strategies library on Angular 19:
dist/scroll-strategies/
βββ fesm2022/
β βββ rdlabo-ngx-cdk-scroll-strategies.mjs
β βββ rdlabo-ngx-cdk-scroll-strategies.mjs.map
βββ lib/
β βββ dynamic-size-virtual-scroll-strategy.d.ts
β βββ dynamic-size-virtual-scroll.service.d.ts
βββ index.d.ts
βββ package.json
βββ public-api.d.ts
βββ README.md
The original project has src/lib/dynamic-size-virtual-scroll-strategy.ts and src/lib/dynamic-size-virtual-scroll.service.ts, so src contents flatten into lib/ as .d.ts files. Angular 20 changed that to:
dist/scroll-strategies/
βββ fesm2022/
β βββ rdlabo-ngx-cdk-scroll-strategies.mjs
β βββ rdlabo-ngx-cdk-scroll-strategies.mjs.map
βββ index.d.ts
βββ package.json
βββ README.md
If you never imported types from lib/dynamic-size-virtual-scroll-strategy, you may not notice (build settings matter too). Related issue: Flatten type definitions to a single *.d.ts file #139.
Libraries also moved from @angular-devkit/build-angular:ng-packagr to @angular/build:ng-packagr.
Experimental API changes
The Resources API had several breaking changes. https://zenn.dev/rdlabo/articles/ff0bc7de29bd65
Also, provideExperimentalZonelessChangeDetection was renamed to provideZonelessChangeDetection. Experimental APIs getting clearer names is welcome.
Summary
I have used Angular since Angular 2. Recently, from Signals through signal-based design and zoneless, the framework keeps getting easier to use.
Above all, I am not thrown by sudden breaking changesβif I follow official upgrade guides, I naturally land on current patterns. It is not flashy, but steady evolution makes it a solid base for products.
See you next time.