Improve Performance in your Angular Application (Part 1)

Improve Performance in your Angular Application (Part 1)

I'm excited to discuss a new feature in Angular 17 called Defer or Deferable Views and how it can greatly improve the performance of our Angular applications.

So first of all you must understand what is the deferrable view.

This is a view that will rendered not initially but later.

Why do we need it at all?

Consider the scenario where you manage a sizable Angular application with numerous elements being rendered on the screen, including various components. In many cases, a significant portion of these components may not be immediately required upon initial page load. Consequently, deferring the loading of such components until they are specifically needed can notably enhance the speed and performance of our application. The core concept here is to prioritize the loading of essential information required for initialization, thereby ensuring that users are presented with only the necessary content upon their initial interaction. In Angular 17 it is possible to do it in an extremely comfortable and flexible way that is called deferred views.

Let's explore an example.

<div>app component view</div>
<div>app component view</div>
<div>app component view</div>
<div>app component view</div>
<div>app component view</div>
@defer {
<app-child></app-child>
}

In the image provided, we observe both the app and app.child components. Notably, the child component isn't necessary for the initial page load, indicating it can be deferred for later loading. Let's confirm this observation in the browser. Upon inspection, you'll notice a slight blinking effect after the child component loads, while the content of the App component remains stable. This behavior is due to the default option of "idle" in defer, where the framework renders this code only after prioritized tasks are completed. To further examine this, let's navigate to the network tab. You'll notice a chunk file that loads relatively late. Examining its contents confirms it precisely matches the content of the child component. This indicates that the child component is dynamically loaded by Angular and not bundled with the initial files.

Defer Triggers

viewport

Now let's check it for triggers, the most popular trigger for sure is on viewport which actually means that we are loading our block only when it comes to the viewport. If it is outside of the viewport we don't load it at all. but it is necessary to use the placeholder annotation when we are using viewport. the placeholder content will be rendered until the child content is loaded. Most importantly we don't load the component chunk file at all we do it only when this element comes to the viewport. That means we are making our application much faster!

<div>app component view</div>
<div>app component view</div>
<div>app component view</div>
<div>app component view</div>
<div>app component view</div>
@defer (on viewport) {
<app-child></app-child>
}
@placeholder {
<div>Placeholder</div>
}

interaction

it will happen when we interact with the block. For example by clicking on it.

hover

It will happen when we hover on the block.

immediate

We try to execute this block as soon as possible after the full page is rendered.

timer(ms)

we try to render the block with a delay that we can pass to the trigger.

However, it is also important that we can combine the triggers for example:

<div>app component view</div>
<div>app component view</div>
<div>app component view</div>
<div>app component view</div>
<div>app component view</div>
@defer (on interaction; on timer(2000)) {
<app-child></app-child>
}
@placeholder {
<div>Placeholder</div>
}

When Condition

we can also add a condition to render the block. check this example:

<div>app component view</div>
<div>app component view</div>
<div>app component view</div>
<div>app component view</div>
<div>app component view</div>

<button (click)="visible = true">Load</button>
@defer (when visible) {
<app-child></app-child>
}
@placeholder {
<div>Placeholder</div>
}

Difference between ngif and defer

It may occur to you that the behaviors of conditional statements in defer views and ngIf may seem similar at first glance. However, it's crucial to recognize that these are two distinct concepts. NgIf simply hides elements from the DOM without rendering them, whereas defer operates differently by not loading anything initially. Instead, it stores the component in additional chunks and loads it when required. Understanding this disparity is essential, particularly in scenarios where ngIf is employed for a large number of elements, such as 2000. In such cases, the performance implications can be significant since all the logic remains intact despite elements being hidden.

Prefetch the chunks file

You can load chunks files using the prefetch keyword. This grants us complete control over when we fetch and render them. Consider this example:

<div>app component view</div>
<div>app component view</div>
<div>app component view</div>
<div>app component view</div>
<div>app component view</div>

<button (click)="visible = true">Show</button>
<button (click)="prefetchEnabled = true">Load</button>
@defer (when visible; prefetch when prefetchEnabled) {
<app-child></app-child>
}
@placeholder {
<div>Placeholder</div>
}

The important point is instead of when prefetchCondition we can use on idle keyword which means we will prefetch this specific chunk as soon as we have resources for that and this is the best part of the defer, because we always want to load everything as soon as possible to make transitions for user much faster.

I hope you found this article enjoyable to read.