Contents

On November 19, 2024, the Angular team officially released Angular 19, continuing the tradition of delivering exciting new features with every update. This version prioritizes enhancements to flexibility, scalability, and application performance while simplifying the developer experience. Let’s dive into some of the Angular 19 features that will help you streamline your development workflow and enable the creation of faster, more efficient web applications.

1. Incremental Hydration in developer preview

Hydration is the process of “activating” a server-rendered page on the client side by adding interactivity. When an application is server-side rendered (SSR), the server generates an HTML document and sends it to the client. On the client side, Angular needs to take over and add interactivity to the static HTML – known as “hydration.”

In traditional Angular SSR (read more about Angular SSR implementation in my colleague – Paweł Żurawski’s – article), the entire application is hydrated in a single go once the client receives the HTML. This can be inefficient, especially if the application is large or complex, because the entire page has to be bootstrapped all at once, which can lead to delays in making the page interactive.

Incremental hydration is a cutting-edge feature aimed at optimizing the performance of server-side rendered applications by improving the loading and execution of JavaScript on the client side. This feature helps reduce the time it takes for the page to become interactive by incrementally bootstrapping parts of the application instead of doing it all at once. Angular hydrates smaller parts of the application incrementally as needed.

How does it work?

With incremental hydration, Angular will break up the application into smaller “hydration zones” or “hydration chunks.” When the client receives the server-rendered HTML, Angular will start hydrating the essential or visible parts of the page first. Once those are interactive, Angular will continue to hydrate the remaining areas of the page in the background.

Incremental hydration lets you mark sections of your template with the familiar @defer syntax (introduced in Angular 17), directing Angular to lazy load and hydrate them only when certain triggers occur.

Example:

@defer (hydrate on viewport) {
 <your-component />
}

You can read more about incremental hydration in the documentation.

2. Event replay becomes stable

Event replay is a feature in Angular that ensures the seamless execution of user interactions in server-side rendered (SSR) or partially hydrated applications.

This mechanism captures and queues user interactions (e.g., clicks, form submissions, and scrolls) that occur before the application is fully hydrated. Once the hydration process is complete and the client-side JavaScript takes control, these queued events are replayed and handled as if they had occurred after hydration.

Starting with Angular 19, event replay is stable and enabled by default for all new applications that use server-side rendering, making them more robust and interactive without requiring additional configuration.

The Angular CLI will now generate this setup by default:

bootstrapApplication(App, {
  providers: [
    provideClientHydration(withEventReplay())
  ]
});

3. Standalone by default

Standalone components were introduced in v14, and over 90% of developers in the last developer survey claimed they use this feature. In Angular 19, standalone components are now the default way to define and build Angular components. This change simplifies the metadata of all your standalone components, directives, and pipes.

When updating to v19, the CLI will automatically remove the standalone metadata property for all standalone abstractions, set to false for non-standalone ones.

4. Strict standalone enforcement

To enforce modern APIs in your project, a compiler flag has been introduced. It will trigger an error if it detects a component, directive, or pipe that isn’t standalone. To enable this feature, configure tsconfig.json file as follows:

{
  "angularCompilerOptions": {
    "strictStandalone": true
  }
}

[..]
[ERROR] TS-992023: Only standalone components/directives are allowed when 'strictStandalone' is enabled. [plugin angular-compiler]

5. Experimental reactive primitive: linkedSignal

 

The linkedSignal in Angular is an experimental API that introduces a new way to manage a state that is intrinsically linked to other reactive states. This feature is particularly useful in scenarios where a piece of a state depends on another and should update accordingly when the source state changes.

linkedSignal creates a writable signal that automatically updates its value based on a computation function whenever its source signal changes. This ensures that the dependent state remains consistent with its source.

Unlike computed signals, which are read-only, linkedSignal allows for manual updates. This means you can set its value directly, providing flexibility in managing states that may need both automatic and manual adjustments.

How does it work?

For simpler scenarios, you can use shorthand syntax:

animals = signal(['guinea pig', 'cat', 'dog']);

selectedAnimal = linkedSignal(() => animals()[0]);
console.log(selectedAnimal()); // 'guinea pig'

animals.set(['elephant','rabbit']);
console.log(selectedAnimal()); // 'elephant'

Every time the animals array changes, the selectedAnimal will change to the first one from a new list.

In some cases, a new value has to be computed based on the previous value. This is where you might consider using more advanced syntax with source and computation:

animals = signal<string[]>(['guinea pig', 'cat', 'dog']);

selectedAnimal = linkedSignal({
    source: animals,
    computation: (newAnimals: string[], previous?: { value: string }) => {
      // If the previous selection exists in the new list, keep it. Otherwise, use the first animal.
      return previous && newAnimals.includes(previous.value)
        ? previous.value
        : newAnimals[0];
    },
  });


// Keep current selection while resetting animals list (for example: re-fetching from API)
console.log(this.selectedAnimal()); // 'guinea pig'
this.animals.set(['horse', 'guinea pig']);
console.log(this.selectedAnimal()); // 'guinea pig'
this.animals.set(['horse', 'fish']);
console.log(this.selectedAnimal()); // 'horse'

// Since linkedSignal is writable, animal can also be selected manually (for example: after selection from UI)
this.selectedAnimal.set('dog');
console.log(this.selectedAnimal()); // 'dog'

You can read more about linkedSignals in the documentation.

6. Experimental streamlining data retrieval: resource and rxResource APIs

Angular 19 introduces experimental resource and rxResource APIs to streamline asynchronous data retrieval and management by leveraging signals and observables. It’s worth pointing out that both APIs may yet undergo changes before becoming stable in future releases.

resource API

The resource function creates a reactive data source that fetches asynchronous data and provides signals to monitor its state.

Main features:

  • Reactive requests – Define a request function that returns parameters based on signals. When these signals change, the loader function re-executes to fetch updated data.
  • Loader function –  Perform the asynchronous operation, returning a Promise of the resource’s value. It receives an abortSignal to handle request cancellations when parameters change during an ongoing fetch.
  • State management – Access the resource’s state through signals like value, status, error, and isLoading, enabling efficient handling of loading states and errors.

Example usage:

const RESOURCE_URL = 'https://lorem.ipsum';
const id = signal(1);

const myResource = resource({
  request: () => ({ id: id() }),
  loader: ({ request, abortSignal }) =>
    fetch(`${RESOURCE_URL}${request.id}`, { signal: abortSignal }).then(response => response.json()),
});

In this example, myResource fetches data based on the id signal. Changing id triggers a new fetch, with the previous request aborted if still in progress.

rxResource API

The rxResource function offers similar functionality but, while resource() uses a promise-based loader, rxResource() integrates with RxJS observables, catering to developers who prefer using observables for asynchronous operations. It is suited for more complex scenarios involving streams of data and leverages the full power of RxJS to handle retries, cancellations, combining streams, and more. Currently, rxResource considers only the first emitted value from the observable; subsequent emissions are ignored.

Example usage:

const RESOURCE_URL = 'https://lorem.ipsum';
const id = signal(1);

const myRxResource = rxResource({
  request: () => ({ id: id() }),
  loader: ({ request }) =>
    fromFetch(`${RESOURCE_URL}${request.id}`).pipe(
      switchMap(response => response.json())
    ),
});

Here, myRxResource fetches data as an observable stream, reacting to changes in the id signal.

7. Hybrid rendering (server route configuration) in developer preview

In Angular 19, server route configuration has been introduced to provide developers granular control over how each route in their application is rendered. This feature allows you to specify the rendering mode for individual routes, choosing between Server-Side Rendering (SSR), Static Site Generation (SSG), or Client-Side Rendering (CSR).

How it works?

To configure server routes, you define an array of ServerRoute objects, typically in a file named app.routes.server.ts. Each ServerRoute specifies a path and its corresponding rendering mode using the RenderMode enum.

Example usage:

import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [
  {
    path: '', // Root path
    renderMode: RenderMode.Client, // Rendered on the client (CSR)
  },
  {
    path: 'about',
    renderMode: RenderMode.Prerender, // Prerendered at build time (SSG)
  },
  {
    path: 'profile',
    renderMode: RenderMode.Server, // Rendered on the server per request (SSR)
  },
  {
    path: '**', // Wildcard route for all other paths
    renderMode: RenderMode.Server, // Default to SSR
  },
];

Angular 19 introduces three rendering modes that can be assigned to routes:

  • Server (RenderMode.Server) – Renders the application on the server for each request, providing a fully populated HTML page. This is beneficial for dynamic content that changes per user or request.
  • Prerender (RenderMode.Prerender) – Generates static HTML files at build time for specified routes. Ideal for static content that doesn’t change frequently, enhancing performance through static site generation (SSG).
  • Client (RenderMode.Client) – Renders the application entirely in the browser, following the traditional client-side rendering approach.

8. Warnings for unused standalone imports 

Starting with Angular 19, the Angular CLI includes a feature that reports warnings for unused imports in your application. This enhancement aims to improve code cleanliness and developer productivity by helping you identify unnecessary or obsolete imports in your project files.

Example:

@Component({
  selector: 'test-component',
  imports: [IconComponent],
  templateUrl: './test-component.component.html',
})

[...]

[WARNING] TS-998113: All imports are unused [plugin angular-compiler]
imports: [IconComponent]

Conclusion

Angular evolves rapidly – the 19th version brings a wealth of improvements to enhance the developer experience and general performance of Angular apps. Analyze these functionalities and start incorporating them into your own Angular projects and workflow – they’re bound to make your life easier in various circumstances. 

If you’re interested in more Angular content, check some of the other publications on our blog:

  1. Angular SSR: Your server-side rendering implementation guide
  2. Angular vs React: In-depth comparison of the most popular front-end technologies
  3. Angular MVVM, MVC, CBA – A look at different approaches to application architecture
  4. Keycloak-Angular integration: Practical tutorial for connecting your app to a powerful IAM system
  5. AngularJS upgrade: Why 2023 is the time for migrating and how to do it

Angular 19 FAQ

Here are answers to some common questions regarding Angular applications, features, and development. 

What is the current Angular version?

The current version is Angular 19.

What are the best Angular 19 new features?

Some of the standout features include incremental hydration, stable event replay, standalone changes, the new experimental linked signal primitive, experimental streaming data retrieval APIs, hybrid rendering, and warnings for unused standalone imports.

What is the Angular 19 release date?

Angular 19 was released on November 19, 2024.

What is Angular Material UI?

It’s a comprehensive components library for material design in Angular.

What is Angular language service?

The Angular Language Service helps code editors with error handling and identification, getting completions and hints, and navigating inside Angular templates.

What is hot module replacement in Angular?

Hot module replacement (HMR) allows developers to replace application components and modules in real time (during runtime) without losing the application state.

Share