What is Differential Loading in Angular v8?

Share with your friends!

This article was originally published on my Linkedin account. You can find it here. https://www.linkedin.com/pulse/what-differential-loading-angular-v8-dhanushka-chandana/

It is Angular 8.0.0 release here! With lots of cool features. They have made Angular to another level in Modern web application development. This major release covered the entire platform, including the framework, CLI with synchronized major versions, and Angular Material.

This release improves application startup time on modern browsers, provides new APIs for tapping into the CLI, and aligns Angular to the ecosystem and more web standards.

Back to topic…

Differential Loading is one of the features that came out with this major release. It is a mechanism of choosing the browser between modern or legacy JavaScript based on its own capabilities. Currently taking advantage of this by default by performing a modern build and a legacy build of the application. When users load the application, they’ll automatically get the bundle they need.

The CLI can understand browsers which the app needs to support and can make different bundles for both ES5 browsers and not.

In Differential Loading,

  • Produce ES5 modules for newer browsers
  • Do not downgrade modern level features
  • Do not send polyfills for the modern browsers

That means above flow guarantees the smaller payload and faster execution.

If you use ng update, automatically updates your tsconfig.json. Then you can take advantage of this. Angular CLI looks at the target JS level in your tsconfig.jsonto determine whether or not to take advantage of Differential Loading.

{
	  "compilerOptions": {
	  …

	  "module": "esnext",
	  "moduleResolution": "node",
	  …
	  "target": "es2015",
	  …
	},

When the target is set to es2015, Angular generate and label two bundles as on the scripts tags in the following capture.

The html file with modern and legacy modules

Legacy browsers use,

<script nomodule src="app-es5.js"></script>

Modern browsers use,

<script type="module" src="app-es2015.js"></script>

How to use

To enable differential loading, the app must have browserslist configuration. It can be placed in package.json or browserslist file. Apps created recently by CLI should contain it and you can find it in the project.

  • Set the target to es2015 in tsconfig.js
  • Set the minimum supported browsers in browserlist

Angular CLI knows how to handle this. The CLI judges whether the app has to support ES5 browsers, and check the current tsconfig’s target can support them. 

If they are mismatched, all bundles are separated as like app-es5.js and app-es2015.js.

Let’s check how the browser reacts for this.

The browser follows the 3-step process in order to run the application with differential loading capability.

  1. Load HTML
  2. Look at script tags
  3. Download the correct version

This ensures on modern browsers, users will load bundles in a smaller size just that the browser needs. It can improve loading performance.

Opting out of differential loading

Differential loading can be explicitly disabled if it causes unexpected issues or you need to target ES5 specifically for legacy browser support.

To explicitly disable differential loading:

  • Enable the dead or IE browsers in the browserslist config file by removing the not keyword in front of them.
  • Set the target in the compilerOptions to es5.

As Angular Team says,

This feature saved over 40kB of initial bundle size for modern browsers. From the community They’ve heard that applications generally save 7–20% of their bundle size, depending on the number of modern JavaScript features they take advantage of.

PS: Angular CLI v7.3 added a feature like differential loading but only for polyfills. It uses es5BrowserSupport option in angular.json. This will be deprecated since maintaining both supporting browsers in both of browserslist for CSS and es5BrowserSupport for JavaScript is an additional overhead.

Leave a Reply

Your email address will not be published. Required fields are marked *