Deferrable Views: A New Performance Boost for Angular Applications
Tags: angular, webdev, javascript
Published: 2023-11-27 13:50:34

Angular continue to surprise us with it's updates per version. In this new version Angular have also changes it's brand and documentation [Angular 17](https://angular.dev/). The major release of Angular Framework came with a number of new features and improvements, including:

> **`Deferrable views`**: 
Defeferrable views are a new feature that allows Angular to defer the creation of views until they are actually needed. This can improve performance, especially for large applications.

This groundbreaking feature enables developers to create applications that load views only when they are needed, leading to a noticeable improvement in initial rendering times and overall user experience.
The ability to defer view creation introduces a new level of flexibility and control over how Angular applications load. Developers can now prioritize the rendering of essential content, while deferring the loading of less critical views until the user interacts with the application.

> **How to Use Deferrable Views**

Implementing deferrable views in Angular 17 is straightforward. Developers can utilize the defer attribute on template elements to indicate that the view should be created lazily. The loadChildren directive can also be used to defer the loading of external components.

Here is an example of how to use deferrable views to defer the loading of a component named `CommentComponent`:
``` html
<div *ngIf="comment">
  <comment defer></comment>
</div>
```

In this example, the `CommentComponent` will only be created when the `comment` property is true.

You can also use a loading block to display placeholder content while the view is being loaded:
``` html
<div *ngIf="comment">
  <loading *ngIf="isLoading"></loading>
  <comment defer></comment>
</div>
```
In this example, the `loading` block will be displayed until the `CommentComponent` is loaded.

We also can have **Loading Content on Demand** as an example for an e-commerce website that has a huge content. For that we can take  the sidebar and footer which can be deferred until the user scrolls down the page. This ensures that the most critical content, such as product listings and search bar, are rendered first, providing a faster and more responsive user experience.
``` html
<div class="container">
  <div>
    </div>

  <div class="sidebar" *defer="on scroll: 100px">
    </div>

  <div class="footer" *defer="on viewport: bottom">
    </div>
</div>
```
In this example, the sidebar and footer are wrapped in *defer directives, indicating that they should be created lazily. The on scroll: 100px trigger specifies that the sidebar should be loaded when the user scrolls down the page by 100px. The on viewport: bottom trigger specifies that the footer should be loaded when the user scrolls to the bottom of the viewport.

The defer directive also supports other triggers, such as on interaction and on timer, providing developers with flexibility to control when deferred views are loaded.

> **Benefits of Deferrable Views**

The introduction of deferrable views brings a multitude of benefits for Angular applications:

- `Improved Initial Rendering Times`: By deferring the creation of non-essential views, Angular can focus on rendering the most critical content first, significantly reducing initial rendering times and improving page load performance.

- `Enhanced User Experience`: Faster initial rendering leads to a smoother and more responsive user experience, especially for users on slower devices or with limited network connectivity.

- `Reduced Memory Usage`: Deferring view creation helps optimize memory usage by only instantiating views when they are actually needed, minimizing the overall memory footprint of the application.

- `Flexible View Loading`: Developers gain greater control over view loading, allowing them to prioritize essential content and defer non-essential views based on user interaction or application logic.

> **Real-World Applications of Deferrable Views**

Deferrable views offer immense potential for optimizing Angular applications across various use cases:

- `Lazy Loading of Large Components`: Break down large components into smaller, deferrable chunks to improve initial rendering and reduce memory usage.
``` html
<app-product-detail>
  <div class="product-image">
    <img src="{{ product.imageUrl }}" alt="{{ product.name }}">
  </div>

  <div class="product-details">
    <h2>{{ product.name }}</h2>
    <p>{{ product.description }}</p>
    <p>Price: {{ product.price }}</p>

    <button>Add to Cart</button>
  </div>
</app-product-detail>
```
Breaking Down the Component:
``` html
<app-product-detail>
  <app-product-image *defer="on init">
    <img src="{{ product.imageUrl }}" alt="{{ product.name }}">
  </app-product-image>

  <div class="product-details">
    <h2>{{ product.name }}</h2>
    <p>{{ product.description }}</p>
    <p>Price: {{ product.price }}</p>

    <button>Add to Cart</button>

    <app-product-reviews *defer="on interaction: click">
      </app-product-reviews>
  </div>
</app-product-detail>
```
In this example, the `app-product-detail` component is now divided into two smaller components: `app-product-image` and `app-product-reviews`. The `app-product-image` component contains the product image, which is essential for initial rendering. The `app-product-reviews` component, which contains the product reviews, is deferred until the user clicks on the "Reviews" button.

- `Loading Content on Demand`: Defer loading non-essential content, such as sidebars or tabs, until the user interacts with the corresponding elements.
``` html
<div class="container">
  <div class="main-content">
    ...
  </div>

  <div class="sidebar" *defer="on interaction: sidebarToggle">
    ...
  </div>

  <div class="tabs">
    <button (click)="activateTab('tab1')">Tab 1</button>
    <button (click)="activateTab('tab2')">Tab 2</button>
  </div>

  <div class="tab-content" *defer="on demand: activeTab">
    <ng-template #tab1>
      </ng-template>

    <ng-template #tab2>
      </ng-template>
  </div>
</div>
```
In this example, the sidebar is wrapped in a `*defer` directive with an `on interaction: sidebarToggle` trigger. This means that the sidebar will only be loaded when the user clicks on the sidebar toggle button.

The tabs are also deferrable, using an `on demand: activeTab` trigger. This means that only the content of the currently active tab will be loaded. The `activateTab` method is used to update the `activeTab` property, which in turn triggers the loading of the corresponding tab content

- `Optimizing Mobile Performance`: Prioritize rendering essential content for mobile devices to ensure a seamless user experience on slower networks or devices with limited processing power.
``` html
<div class="product-page">
  <div class="product-image">
    <img src="low-res-image.jpg" alt="Product thumbnail">
    <img *defer="on platform: mobile" src="high-res-image.jpg" alt="Product image">
  </div>

  <div class="product-details">
    <h2>Product Name</h2>
    <p>Product description</p>
  </div>

  <div class="product-animation" *defer="on platform: mobile">
    </div>
</div>
```
In this example, a low-resolution thumbnail image is loaded initially, while the high-resolution image is deferred until the user is on a non-mobile device. Similarly, the complex animation is only loaded if the user is on a non-mobile device.

- `Improving Search Engine Optimization`: Defer loading non-essential content can enhance search engine optimization by reducing page load times and improving perceived performance.
``` html
<div class="container">
  <h1>Product Name</h1>
  <p>Product description</p>

  <div class="product-reviews" *defer="on idle: 5000">
    </div>

  <div class="related-products" *defer="on viewport: 75%">
    </div>
</div>
```
In this example, the non-essential content, such as product reviews and related products, is wrapped in `*defer` directives. These directives indicate that the content should be loaded lazily, meaning it will only be loaded when the user interacts with the page or after a specified delay.

The `on idle: 5000` trigger specifies that the product reviews should be loaded after 5 seconds of user inactivity. This allows the search engine crawler to quickly index the essential content, while the non-essential content is loaded when the user is more likely to engage with it.

The `on viewport: 75%` trigger specifies that the related products should be loaded when the user scrolls to 75% of the viewport. This ensures that the related products are not loaded immediately, which can reduce the initial page load time, but they are still loaded before the user reaches them, providing a seamless user experience.

By deferring the loading of non-essential content, the page load time can be reduced, and the perceived performance can be improved, both of which can positively impact SEO.

`Flexibility in Triggering Deferral`: Deferrable views offer a variety of triggers to control when a view is loaded. Besides the `on scroll`, `on viewport`, `on interaction`, and `on timer` triggers, you can also use custom triggers to defer loading based on specific conditions or events.

`Optimizing for Different Devices`: Deferrable views can be particularly beneficial for mobile applications, where network bandwidth and processing power are often limited. By deferring loading of less critical content, you can ensure that essential components are rendered first, providing a smoother and more responsive experience for mobile users.

`Enabling Lazy Loading of External Components`: The `loadChildren` directive can be used to defer the loading of external components, even when they are not directly part of the template. This allows you to prioritize the loading of essential components and defer the loading of external dependencies until they are actually needed.

`Improving Initial Rendering Times`: Deferrable views contribute to faster initial rendering times by minimizing the amount of content that needs to be loaded at the start. This is especially important for applications with large or complex components.

`Reducing Memory Footprint`: By deferring view creation, you can reduce the overall memory footprint of the application. Only the necessary components are loaded at a given time, minimizing the memory consumption of the application.

`Optimizing for Server-Side Rendering (SSR)`: Deferrable views can be used in conjunction with SSR to improve the perceived performance of server-rendered applications. By deferring the loading of non-essential content, you can ensure that the initial content is rendered quickly, even on slower servers.

`Enhancing Performance for Caching and Code Updates`: Deferrable views can also improve the performance of caching and code updates. By deferring the loading of content that may change frequently, you can reduce the cache invalidation overhead and ensure that the application is updated more efficiently.

In summary, deferrable views represent a significant advancement in Angular's performance optimization capabilities. By enabling developers to defer view creation until they are actually needed, Angular 17 empowers developers to create applications that load faster, use less memory, and provide a more responsive user experience across a wide range of devices and scenarios.