You may have heard about differential loading. It’s a feature that was introduced in the Angular CLI 8 and it creates separate bundles for ES2015 and ES5:
- ES2015 bundles will be loaded by modern browsers
- ES5 bundles will be loaded by older browsers
The main benefit of the ES2015 bundle is that it takes advantage of new language features and requires less polyfills, resulting in a smaller bundle size.
I thought about using this feature to benefit from smaller bundle sizes in my Ionic apps but realized that when packaging the app, shipping two bundles instead of one would not reduce the size, but increase it.
In the context of packaged hybrid mobile apps, it just bloats the app size when you embed separate bundles of the same code.
The reason why I propose not to use differential loading in hybrid mobile apps is that we don’t even need to ship an ES5 bundle. It turns out that mobile browsers have great support for ES2015 (formerly known as ES6) already: https://caniuse.com/#feat=es6
In short, don’t create separate bundles but simply go with ES2015 right away.
Here are the steps on how to configure differential loading for your Angular app to only produce an ES2015 bundle:
Angular CLI 8+:
If you’re using the Angular CLI 8+,
es2015 is already the default compile target. This already produces a bundle for ES2015, but during a production build, Angular’s build process will also generate a bundle for ES5, which is needed for differential loading on older browsers. To keep our package tidy, we want to go for the newer ES2015 bundle only. This means we need to configure Angular’s build process to disable differential loading and only create a single build for ES2015. On top of that, skipping the ES5 bundle generation also speeds up the whole build process. These are the necessary steps:
- Create a file named
browserslistin the root of your Angular/Ionic project (in case you already have such a file, continue with that one)
- Copy the browser settings from the code below or this browserslist template, which represent browsers with full support for ES2015. This defines our minimum feature set and leaves out all browsers which do not support our desired features, effectively disabling browsers which only support ES5:
Chrome >= 71 # let's keep it simple by picking only one desktop browser with full ES2015 support
Android >= 56
ios_saf >= 11
safari >= 11
Angular CLI 7:
If you’re using the Angular CLI 7 or lower, the process is even simpler. All you have to do is configure the TypeScript compiler to target
es2015 instead of
- Open the file tsconfig.json
- In compiler options, set
In addition, we’re turning off es5BrowserSupport:
- Open the file angular.json
- Find or create the build option
projects/app/architect/build/optionsand set it to
That’s it. Our build will now produce only one bundle and our code will run on all modern mobile browsers nevertheless.
If you want to learn more about configuring differential loading, you can read about it in the Angular docs here: Configure Differential Loading. In any case, we’re already set for creating a smaller bundle with less polyfills.
Size and Performance Comparison
After running a new production build on my app Citybikes Vienna using the Angular CLI 7, I figured that creating a modern ES2015 bundle without ES5BrowserSupport reduced the bundle size by 390 kB (-13%):
- Old size: 2953 kB
- New size: 2563 kB (-13%)
Satisfied with this quick win I checked if the smaller bundle size and the difference in the compilation have an actual effect on the app’s performance. While there are more reliable and statistically correct tests, I simply used an actual device and measured the startup time of the app after installation. This video compares the two apps side by side:
On this Samsung Galaxy S9 with Android 8.0 (API level 26), the startup time improved from 613 ms to 532 ms. So, yes, it did speed things up!
Side note: If you calculate the performance gain in the startup time, the saving is also 13%, just like with the file size. But this is only by chance, it doesn’t mean that they are in a relation of proportionality. The important thing to take away here is that the startup time has decreased too, which is yet another quick win.
To wrap it up, the ES5 app is quite fast already, but the ES2015 bundle is still faster and also more efficient in terms of file size. Thanks to the simple configuration options of Angular and Typescript, it’s only a matter of flipping two switches:
- Target: ES2015
- Disable ES5
So, let’s go for it!
If you like to check out the performance yourself, you can get my free bike sharing app here: