|
| 1 | +--- |
| 2 | +title: 'Angular 20 is here!' |
| 3 | +author: Angular Book Team |
| 4 | + |
| 5 | +published: 2025-05-30 |
| 6 | +lastModified: 2025-05-30 |
| 7 | +keywords: |
| 8 | + - Angular |
| 9 | + - Angular 20 |
| 10 | + - Structural Directives |
| 11 | + - vitest |
| 12 | + - Component Suffix |
| 13 | +language: en |
| 14 | +header: angular20.jpg |
| 15 | +--- |
| 16 | + |
| 17 | +Everything new comes in May - or at least a new major version of Angular: |
| 18 | +On **May 28, 2025**, **Angular 20** was released! You can find the release information directly from the Angular team in the official [Angular Blog](https://blog.angular.dev/announcing-angular-v20-b5c9c06cf301). |
| 19 | + |
| 20 | +For migrating to Angular 20, we recommend using the `ng update` command. |
| 21 | +Detailed information on the required steps can be found in the [Angular Update Guide](https://angular.dev/update-guide). |
| 22 | + |
| 23 | +> 🇩🇪 This article is available in German language here: [Angular 20 ist da!](https://angular-buch.com/blog/2025-05-angular20) |
| 24 | +
|
| 25 | + |
| 26 | +## Versions of TypeScript and Node.js |
| 27 | + |
| 28 | +For Angular 20, *at least* the following versions of TypeScript and Node.js are required: |
| 29 | + |
| 30 | +- TypeScript: 5.8 |
| 31 | +- Node.js: 20.19.x or higher, 22.12.x or higher, or 24.0.x or higher |
| 32 | + |
| 33 | +Support for Node.js version 18 has been removed. You can find detailed information about supported versions in the [Angular documentation](https://angular.dev/reference/versions). |
| 34 | + |
| 35 | + |
| 36 | +## The new Coding Style Guide |
| 37 | + |
| 38 | +Angular has evolved significantly in recent years, and many new concepts have been integrated into the framework. |
| 39 | +The Angular documentation was partially out of date: the Coding Style Guide, in particular, had no recommendations for the current status quo. |
| 40 | +This changed with Angular 20: |
| 41 | +The new [Style Guide](https://angular.dev/style-guide) has been heavily revised and streamlined. |
| 42 | +It includes current recommendations and best practices and serves as a guideline for development with current Angular versions. |
| 43 | + |
| 44 | +### No more suffixes: more deliberate naming and new patterns |
| 45 | + |
| 46 | +An important change worth mentioning concerns the suffixes in file and class names: |
| 47 | +The new Style Guide *no longer* recommends using suffixes for components, services, and directives. |
| 48 | +Starting with Angular 20, the CLI no longer generates suffixes like `.component.ts` or `.service.ts` by default. |
| 49 | +This new setting only applies to newly created projects. |
| 50 | + |
| 51 | +The command `ng generate component book-card` thus produces the following output: |
| 52 | + |
| 53 | +**up to Angular 19:** |
| 54 | + |
| 55 | +``` |
| 56 | +src/app |
| 57 | + book-card |
| 58 | + book-card.component.ts |
| 59 | + book-card.component.html |
| 60 | + book-card.component.scss |
| 61 | + book-card.component.spec.ts |
| 62 | +``` |
| 63 | + |
| 64 | +```ts |
| 65 | +// book-card.component.ts |
| 66 | +// ... |
| 67 | +@Component(/* ... */) |
| 68 | +export class BookCardComponent {} |
| 69 | +``` |
| 70 | + |
| 71 | +**starting with Angular 20:** |
| 72 | + |
| 73 | +``` |
| 74 | +src/app |
| 75 | + book-card |
| 76 | + book-card.ts |
| 77 | + book-card.html |
| 78 | + book-card.scss |
| 79 | + book-card.spec.ts |
| 80 | +``` |
| 81 | + |
| 82 | +```ts |
| 83 | +// book-card.ts |
| 84 | +// ... |
| 85 | +@Component(/* ... */) |
| 86 | +export class BookCard {} |
| 87 | +``` |
| 88 | + |
| 89 | +The goal: Angular applications should contain less boilerplate, and we should think more deliberately about naming abstractions. |
| 90 | +Instead of automatically generated constructs like `product-detail.component.ts`, we're now expected to think: What is this class called? What does it do? How much does the name say on its own? |
| 91 | +We welcome this development, as it leads to shorter, more purposeful file and class names. |
| 92 | + |
| 93 | +A practical example: For routed components, we prefer the suffix `page`, such as `checkout-page.ts` (class name `CheckoutPage`). It clearly indicates its purpose without referring to technical details like `Component`. |
| 94 | +A component that only displays content and contains no logic could be named `CheckoutView`, for example. |
| 95 | + |
| 96 | +If you want to keep the previous behavior, you can still specify a `type` when generating, which will result in a suffix. |
| 97 | +This setting can also be made permanent in the `angular.json` file. |
| 98 | + |
| 99 | +```bash |
| 100 | +ng generate component book-card --type=component |
| 101 | +``` |
| 102 | + |
| 103 | + |
| 104 | +## Zoneless Developer Preview |
| 105 | + |
| 106 | +The Angular team has been working for several years to optimize *synchronization* (also known as *change detection*) in the framework. |
| 107 | +One milestone was the introduction of signals, which allow precise change detection. |
| 108 | +In the future, Angular will no longer need the *zone.js* library to patch browser interfaces and trigger change detection. |
| 109 | + |
| 110 | +<!-- We already covered change detection and the setting for a “zoneless application” in detail in our [blog post for Angular 18 (German language)](/blog/2024-06-angular18). --> |
| 111 | + |
| 112 | +With Angular 20, *zoneless* is released in *Developer Preview* status. |
| 113 | +The interface is largely stable. However, short-term changes may still occur, so usage in production should be carefully considered. |
| 114 | + |
| 115 | +To activate zoneless change detection, use the `provideZonelessChangeDetection()` function. |
| 116 | +The word `experimental` has been removed from the function name. |
| 117 | +It's also recommended to enable a global error handler that catches unhandled exceptions. |
| 118 | + |
| 119 | +```ts |
| 120 | +// app.config.ts |
| 121 | +export const appConfig: ApplicationConfig = { |
| 122 | + providers: [ |
| 123 | + provideZonelessChangeDetection(), |
| 124 | + provideBrowserGlobalErrorListeners() |
| 125 | + ] |
| 126 | +}; |
| 127 | +``` |
| 128 | + |
| 129 | +The Angular CLI offers to generate a *zoneless* application when creating a new project: |
| 130 | + |
| 131 | +```bash |
| 132 | +➜ ~ ng new my-app |
| 133 | +✔ Do you want to create a 'zoneless' application without zone.js (Developer Preview)? Yes |
| 134 | +``` |
| 135 | + |
| 136 | +The setting can also be controlled with the new `zoneless` parameter, which can be negated using `no`: |
| 137 | + |
| 138 | +```bash |
| 139 | +ng new my-app --zoneless |
| 140 | +ng new my-app --no-zoneless |
| 141 | +``` |
| 142 | + |
| 143 | + |
| 144 | +## Structural directives `ngIf`, `ngFor`, `ngSwitch` |
| 145 | + |
| 146 | +With Angular 20, the old directives `ngIf`, `ngFor`, and `ngSwitch` are marked as *deprecated*. |
| 147 | +They will likely be completely removed from the framework with Angular 22 (in one year). |
| 148 | + |
| 149 | +The background is the new built-in control flow introduced with Angular 17. |
| 150 | +These directives can be replaced by Angular's built-in expressions: `@if`, `@for`, `@switch`, and `@let`. |
| 151 | + |
| 152 | +```html |
| 153 | +<!-- with directive (deprecated) --> |
| 154 | +<div *ngIf="condition">Hello world</div> |
| 155 | + |
| 156 | +<!-- with control flow --> |
| 157 | +@if (condition) {<div>Hello world</div>} |
| 158 | +``` |
| 159 | + |
| 160 | +<!-- We covered the control flow syntax in detail in our [blog post on Angular 17](/blog/2023-11-angular17#neuer-control-flow-if-for-switch). --> |
| 161 | +The Angular CLI also provides a migration script, so switching to the new syntax shouldn't be difficult: |
| 162 | + |
| 163 | +```bash |
| 164 | +ng generate @angular/core:control-flow |
| 165 | +``` |
| 166 | + |
| 167 | + |
| 168 | +## Experimental test builder for Vitest |
| 169 | + |
| 170 | +The test runner Karma, still the default for unit and integration tests in Angular, is no longer being developed. |
| 171 | +Since this decision, the Angular team has been working on integrating alternative test runners into the Angular CLI. |
| 172 | +Two years ago, experimental builders for [Jest and Web Test Runner](https://blog.angular.dev/moving-angular-cli-to-jest-and-web-test-runner-ef85ef69ceca) were released. |
| 173 | +With Angular 20, another experimental integration is added for [Vitest](https://vitest.dev): |
| 174 | +Vitest has already become a staple in other web frameworks based on the [Vite](https://vite.dev) bundler. |
| 175 | +Angular's build process has already [used ESBuild with Vite since version 16](/blog/2023-05-angular16#esbuild). |
| 176 | +With this gradual switch, we can now also use Vitest for unit and integration tests. |
| 177 | + |
| 178 | +Which of the experimental test runners will become Angular's new standard is not yet decided! |
| 179 | +All approaches are experimental and will be evaluated further in the coming months. |
| 180 | + |
| 181 | +To use Vitest with the Angular CLI, first add the required dependencies: |
| 182 | + |
| 183 | +```sh |
| 184 | +npm i vitest jsdom --save-dev |
| 185 | +``` |
| 186 | + |
| 187 | +Then, adjust the testing configuration in the `angular.json` file: |
| 188 | + |
| 189 | +```json |
| 190 | +"test": { |
| 191 | + "builder": "@angular/build:unit-test", |
| 192 | + "options": { |
| 193 | + "tsConfig": "tsconfig.spec.json", |
| 194 | + "buildTarget": "::development", |
| 195 | + "runner": "vitest" |
| 196 | + } |
| 197 | +} |
| 198 | +``` |
| 199 | + |
| 200 | +In your tests, use Vitest's functions by importing the following: |
| 201 | + |
| 202 | +```ts |
| 203 | +import { describe, beforeEach, it, expect } from 'vitest'; |
| 204 | +// ... |
| 205 | +``` |
| 206 | + |
| 207 | +Run the tests as usual using `ng test`. |
| 208 | + |
| 209 | +Vitest is largely compatible with the APIs of [Jest](https://jestjs.io/) and Karma, so switching is definitely worth trying. |
| 210 | +Ideally, you'll need only minimal changes in your tests. |
| 211 | + |
| 212 | +One of the three experimental builders (Jest, Web Test Runner, Vitest) will likely become the new standard. |
| 213 | +We welcome the move to rely on established standards outside the Angular ecosystem and to deprecate the custom Karma test runner. |
| 214 | +We'll continue to keep you updated. |
| 215 | + |
| 216 | + |
| 217 | +## Stable Signal APIs: `effect`, `linkedSignal`, and `toSignal` |
| 218 | + |
| 219 | +Since Angular 16, signals have paved the way for a new, reactive Angular. |
| 220 | +In Angular 20, more APIs from the signals ecosystem have now been officially released as stable: `effect`, `linkedSignal`, and `toSignal`. |
| 221 | + |
| 222 | +These functions were previously experimental and are now part of the stable API set: |
| 223 | + |
| 224 | +* `effect()` automatically reacts to signal changes and performs defined side effects - without lifecycle hooks. |
| 225 | +* `linkedSignal()` enables bidirectional binding between a signal and an external source - e.g. a component or a FormControl. |
| 226 | +* `toSignal()` converts observable data into a readable signal - ideal for integrating existing streams. |
| 227 | + |
| 228 | +You'll find more details and examples in our Signals series: |
| 229 | + |
| 230 | +* [Angular 19: Introducing LinkedSignal for Responsive Local State Management](https://angular.schule/blog/2024-11-linked-signal) |
| 231 | +* [Angular 19: Mastering effect and afterRenderEffect](https://angular.schule/blog/2024-11-effect-afterrendereffect) |
| 232 | + |
| 233 | + |
| 234 | +## httpResource: Load data with signals |
| 235 | + |
| 236 | +In October 2024, the new experimental Resource API was introduced. We covered it in detail in a [blog post](https://angular.schule/blog/2025-05-resource-api). |
| 237 | +It connects the synchronous world of signals with asynchronously fetched data, e.g. via HTTP. |
| 238 | +The data is loaded asynchronously using a loader and provided via signals. |
| 239 | + |
| 240 | +A few weeks ago, another variant of the Resource was introduced: `httpResource`. |
| 241 | +It uses Angular's `HttpClient` under the hood to perform an HTTP request directly. |
| 242 | +You no longer need to write the request yourself - the resource handles it for you. |
| 243 | + |
| 244 | +```ts |
| 245 | +booksResource = httpResource<Book[]>( |
| 246 | + () => 'https://api.example.org/books', |
| 247 | + { defaultValue: [] } |
| 248 | +); |
| 249 | +// ... |
| 250 | +console.log(booksResource.value()) |
| 251 | +``` |
| 252 | + |
| 253 | +The request must be generated using a function. |
| 254 | +This is because it runs in a *reactive context*: If you use signals inside the function, the request is re-executed automatically when any of those signals change. |
| 255 | +Additional request details can be passed in an options object: |
| 256 | + |
| 257 | +```ts |
| 258 | +booksResource = httpResource<Book[]>( |
| 259 | + () => ({ |
| 260 | + url: 'https://api.example.org/books', |
| 261 | + params: { |
| 262 | + search: 'Angular' |
| 263 | + } |
| 264 | + }) |
| 265 | +); |
| 266 | +``` |
| 267 | + |
| 268 | +Please note that a resource is only meant for *retrieving* data from an API and exposing it with signals. |
| 269 | +Write operations such as create, update, or delete cannot be handled with a resource. |
| 270 | +You must continue to use `HttpClient` directly for those. |
| 271 | + |
| 272 | + |
| 273 | +## Miscellaneous |
| 274 | + |
| 275 | +You can always find all details about the updates in the changelogs for [Angular](https://github.com/angular/angular/blob/main/CHANGELOG.md) and the [Angular CLI](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md). |
| 276 | +We've compiled a few interesting highlights here: |
| 277 | + |
| 278 | +- **`provideServerRouting()` deprecated:** The function `provideServerRouting()` is deprecated. Instead, use `provideServerRendering()` with the `withRoutes()` feature. (see [commit](https://github.com/angular/angular-cli/commit/33b9de3eb1fa596a4d5a975d05275739f2f7b8ae)) |
| 279 | +- **Chrome DevTools:** Integration of Angular into Chrome DevTools has significantly improved. The *Performance* tab now lets you analyze Angular's change detection and other performance parameters. |
| 280 | +- **Official mascot:** The Angular team wants to introduce an official mascot for the framework - and the community is invited to participate! Vote for your favorite or share your thoughts in the [RFC on GitHub](https://github.com/angular/angular/discussions/61733). |
| 281 | + |
| 282 | +<hr> |
| 283 | + |
| 284 | + |
| 285 | +We wish you lots of fun developing with Angular 20! |
| 286 | +Do you have questions about the new version or about our book? Reach out to us! |
| 287 | + |
| 288 | +**Best wishes from |
| 289 | +Ferdinand, Danny, and Johannes** |
| 290 | + |
| 291 | +<hr> |
| 292 | + |
| 293 | +<small>**Cover photo:** Morning mood at Anklamer Stadtbruch wetland. Photo by Ferdinand Malcher</small> |
0 commit comments