New Angular v17 feature: deferred loading
Tags: angular, typescript, javascript
Published: 2023-10-17 06:42:47

---
title: New Angular v17 feature: deferred loading
published: true
description: Next level lazy-loading demonstrated by using a Signal-based and other examples
tags: angular, typescript, javascript
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zpoojvudcg15mbdbcnn4.png
# Use a ratio of 100:42 for best results.
# published_at: 2023-10-16 18:46 +0000
canonical_url: https://www.angularaddicts.com/p/angular-17-feature-deferred-loading-with-signals
---


**Angular 17** will be released in the beginning of November, and it has an exciting new feature called **deferred loading** ([RFC](https://github.com/angular/angular/discussions/50716)).

**Lazy loading** is a technique that enables web apps to load resources (such as scripts) only when they are needed. Instead of loading all content upfront when the page initially loads, lazy loading defers the loading of non-essential content until the user interacts with the page, scrolls, or reaches a specific point in the page.

Lazy loading enhances the user experience, as it **reduces the initial page load time** and ensures that **users can start interacting with the app as soon as possible**, while non-essential parts of the app load in the background. It reduces the required bandwidth and the server load.

In the previous Angular versions, we can lazy-load a part of the application using the `Router`, or we can use dynamic `import`s and `ngComponentOutlet`. 

In Angular 17, the Angular team will push lazy-loading to the next level: Angular now has a `@defer` control block enabling lazy-loading of the content of the block. Lazy-loading **also applies to the dependencies of the content of the block**: all the components, directives and pipes will be lazy-loaded, too.

In this article, I demonstrate the key aspects of lazy loading in Angular 17, such as

* how we can specify a **logical expression** to trigger the rendering of a deferred block
* how we can define a **declarative** trigger condition to trigger the rendering (for example `on hover`), which trigger types are supported
* how to show a **placeholder**, a **loading state** or an **error state** with additional `@placeholder`, `@loading` and `@error` blocks
* how prefetching work

The full source code is available here:

[https://github.com/gergelyszerovay/angular-17-deferred-loading](https://github.com/gergelyszerovay/angular-17-deferred-loading)

I used Angular v17.0.0-next.8 with standalone components and Signals. You can start the frontend by `yarn run start` or `npm run start`.


## Using `@defer` with a logical expression

In the first example, I create a checkbox and bind it to the `isCheckedDefer` signal. The signal's default value is `false`, so initially the checkbox is unchecked, and the content of the `@defer` block is not rendered. The examples below are from the [src\app\app.component.html](https://github.com/gergelyszerovay/angular-17-deferred-loading/blob/main/src/app/app.component.html) template file:


```html
<div>
  <input #checkboxDefer type="checkbox" [checked]="isCheckedDefer()" (change)="isCheckedDefer.set(checkboxDefer.checked)" id="checkboxDefer"/>
  <label for="checkboxDefer">Open the network tab of the browser's developer tools, then check this checkbox to load the <strong>app-c1</strong> component</label>
</div>
<br>

@defer (when isCheckedDefer()) {
  <app-c1/>
}
@placeholder {
  <span>Placeholder</span>
}
@error {
  <span>Error</span>
}
@loading(minimum 1s) {
  <span>Loading...</span>
}
```


The `@defer (when logical_expression) {` statement creates a `@defer` block with the logical expression. I use the `isCheckedDefer()` signal as a logical expression, as it evaluates to a boolean value.

I added thrre different block types under the `@defer` block, so there is:

* A `@defer` block, Angular renders it, when the `isCheckedDefer` signal's value becomes `true.` It contains a child component: `&lt;app-c1/>`
* A `@placeholder` block, it's rendered initially, before the  `@defer` block is triggered
* When the `@defer` block is triggered, Angular loads the block's content from the server. During the loading, it shows the `@loading` block
* If the loading fails, Angular shows the `@error` block

The use of the `@placeholder`, `@loading` and `@error` blocks are optional, so we can use standalone `@defer` blocks, too.

Let's see how this code works! When we open the app, the `isCheckedDefer` signal is `false`, so the `@defer` block is not triggered and the content of the `@placeholder` block is visible:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5c7coc3b21omv7fjdrfo.png)

Open the Network tab of your browser's Developer tools, and clear it.

When we check the checkbox, the `isCheckedDefer` signal becomes `true`, so Angular loads the content of the `@defer` block. It removes the content of the `@placeholder` block, and renders the content of the `@loading` block. I specified a `minimum` condition for this block, so it'll be visible for at least one second. It's also possible to specify an `after` condition, it allows us to set a minimum duration time to wait before Angular shows the content of the loading block. If the content of the `@defer` block is loaded during this duration, Angular does not show the content of the `@loading` block.

So the content of the `@loading` block is visible for one second:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dk1j7pmsaarjv0qrjmeh.png)

Then the content of the `@defer` block, the `&lt;app-a1>` component is shown:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ibgpz3esl2e6y1evzxao.png)

In the Developer tools we can see that after checking the box, Angular loaded a new chunk of the application, containing the content of the `@defer` block:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ma2fxewg4m06vaknugkp.png)

Now we reload the app, clear the content of the Network tab, then block the network requests in the browser:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/91gmidqg4u1urq9hwi9w.png)

When we check the checkbox, the `isCheckedDefer` signal becomes `true`, so Angular loads the content of the `@defer` block. It removes the content of the `@placeholder` block, and renders the content of the `@loading` block. 

Then loading fails with a network connection error, so Angular shows the content of the `@error` block: 
 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k1i6sac0o4405yjrpyd5.png)

## Using `@defer` with a declarative trigger condition

Deferred blocks support the following declarative trigger types:

* `on interaction`
* `on hover`
* `on idle`
* `on timer`
* `on viewport`

Let's create an example for all of these!

### `@defer on interaction`

Angular renders the `on interaction` block, when the user interacts with its `@placeholder` block. An interaction can be a click, touch focus, or input events, like `keypress`:


```html
@defer (on interaction) {
  <span>Clicked</span>
}
@placeholder {
  <span>Placeholder (click on it!)</span>
}
```

### `@defer on hover`

Angular renders the `on hover` block, when the user hovers over its `@placeholder` block:


```html
@defer (on hover) {
  <span>Hovered</span>
}
@placeholder {
  <span>Placeholder (hover it!)</span>
}
```

### `@defer on idle`

Angular renders the `on idle` block, when the browser reaches an idle state after the page has been loaded:

```html
@defer (on idle) {
  <span>Browser has reached an idle state</span>
}
@placeholder {
  <span>Placeholder</span>
}
```

### `@defer on timer`

The `on timer` block is rendered after the specified time is elapsed:

```html
@defer (on timer(5s)) {
  <span>Visible after 5s&lt;/span>
}
@placeholder {
  <span>Placeholder&lt;/span>
}
```

### `@defer on viewport`

Angular renders the `on viewport` block, when the placeholder enters the browser's viewport:


```html
@defer (on viewport) {
  <app-c2 text="The block entered the viewport"/>
}
@placeholder {
  <span>Placeholder</span>
}
```

After reloading the app, we can check using the inspector tool whether the content of the `@placeholder` block has been rendered in the DOM or not:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zdgv426nscr9st5bfadb.png)

Now follow these steps:

* switch to the Network tab inside your browser's developer tools
* clear the content of the Network tab
* scroll all the way down to the bottom of the page

As a result, Angular loads and renders the content of the `@defer` block (the `<app-c2>` component):

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7n71cz0ogkiqg0hf7qnl.png)

## Prefetching

Next to a trigger condition, we can specify an additional `prefetch` condition:

```html
@defer (on interaction; prefetch on hover) {
  <app-c3/>
}
@placeholder {
  <span>Placeholder (hover it, then click on it!)</span>
}
```

Reload the app, then follow these steps:

* clear the content of the "Network" tab
* hover over the placeholder in the “Prefetch“ section

As a result, Angular loads the content of the `@defer` block, but it's not rendered, the `@placeholder` remains visible:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mr6c80xumpejyn641iaa.png)

Then we click on the placeholder, and Angular renders the prefetched block (the `<app-c3>` component):

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fv20dbzfnfsoeg3blu5i.png)

## Summary

In this article, I demonstrated some of the great new features of Angular 17: I showed you how the new deferred blocks work and how to specify conditions to trigger the loading and rendering these blocks' content. I hope you have found my tutorial useful!

In the second part of this article series, I'll show you how the new control flow (`@if`, `@else`, `@switch` and `@case` blocks) works in Angular 17.

And as always, please let me know if you have some feedback!

## 👨‍💻About the author

My name is [Gergely Szerovay](https://www.linkedin.com/in/gergelyszerovay/), I work as a frontend development chapter lead. Teaching (and learning) Angular is one of my passions. I consume content related to Angular on a daily basis — articles, podcasts, conference talks, you name it.

I created the Angular Addict Newsletter so that I can send you the best resources I come across each month. Whether you are a seasoned Angular Addict or a beginner, I got you covered.

Next to the newsletter, I also have a publication called — you guessed it — [Angular Addicts](https://angularaddicts.com/). It is a collection of the resources I find most informative and interesting. Let me know if you would like to be included as a writer.

Let’s learn Angular together! [Subscribe here](https://www.angularaddicts.com/) 🔥

Follow me on [Substack](https://www.angularaddicts.com/), [Medium](https://medium.com/@GergelySzerovay), [Dev.to](https://dev.to/gergelyszerovay), [Twitter](https://twitter.com/GergelySzerovay) or [LinkedIn](https://www.linkedin.com/in/gergelyszerovay/) to learn more about Angular!