From the Trenches of the Enterprise Software

Yakov Fain

Subscribe to Yakov Fain: eMailAlertsEmail Alerts
Get Yakov Fain via: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn

Blog Feed Post

Angular CLI: dev and prod builds with JiT and AoT

I’m happy to announce that my colleague Anton and I started working on the second edition of our Angular book published by Manning. The new TOC is here. The major changes in the second edition are:

– Get rid of any mention of SystemJS – use Angular CLI only
– Replace the chapter on Webpack with the chapter on ngrx
– Add more code samples illustrating various features and techniques

I just finished re-writing the first chapter and would like to offer you a fragment that illustrates the use of Angular CLI for creating dev and prod builds. Your feedback is appreciated.

To make this article more practical, generate a new project Hello CLI using Angular CLi:

ng new hello-cli

Then build the bundles, start the dev server and open the browser on port 4200 by running a single command:

ng serve -o

Now goes the chapter fragment.

Production Builds

The ng serve command bundled the app files but didn’t optimize our Hello CLI application. Open the Network tab in the dev tools of your browser and you’ll see that the browser had to load 2.4MB to render this simple app. In dev mode, the size of the app is not a concern because you run the server locally and it takes the browser only 802 milliseconds to load this 2.4MB of code as shown below.

https://yakovfain.files.wordpress.com/2017/08/ch1_size_jit1.png?w=150&h=105 150w, https://yakovfain.files.wordpress.com/2017/08/ch1_size_jit1.png?w=300&h=210 300w, https://yakovfain.files.wordpress.com/2017/08/ch1_size_jit1.png?w=768&h=537 768w, https://yakovfain.files.wordpress.com/2017/08/ch1_size_jit1.png?w=1024&h... 1024w, https://yakovfain.files.wordpress.com/2017/08/ch1_size_jit1.png 1152w" sizes="(max-width: 760px) 100vw, 760px" />

Now visualize a user with a mobile device browsing the Internet over a regular 3G connection. It’ll take 10 seconds to load the same Hello CLI app. Many people can’t tolerate waiting for 10 seconds for any app except Facebook (30% of the Earth population just lives on Facebook). We need to reduce the size of the bundles before going live.

Applying the -prod option while building the bundles will produce much smaller bundles by optimizing your code, i.e. it’ll rename your variables into single-letter ones, will remove comments and empty lines, and will remove the majority of the unused code. There is another piece of code that can be removed from the app bundles – the Angular compiler. Yes, the ng serve command included such compiler into the vendor.bundle.js. In the next section will talk about production builds and how to remove the Angular compiler from your deployed app.

JiT and AoT Compilations

Take a look at the code of the generated app.component.html.

<div style="text-align:center">
    Welcome to {{title}}!
  <img width="300" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOS4xLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAw...">
<h2>Here are some links to help you start: </h2>
    <h2><a target="_blank" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
    <h2><a target="_blank" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
    <h2><a target="_blank" href="http://angularjs.blogspot.com/">Angular blog</a></h2>

For the most part, it consists of standard HTML tags, but there is one line that browsers won’t understand:

Welcome to {{title}}!

These double curly braces represent binding a value into a string in Angular, but this line has to be compiled by the Angular compiler (it’s called ngc) to replace the binding with something that browser would understand. A component template can include another Angular-specific syntax (e.g. structural directive *ngIf and *ngFor) that need to be compiled before asking the browser to render the template.

When you run the ng serve command, the template compilation is performed inside the browser. After the browser loads your app bundles, the Angular compiler (packaged inside vendor.bundle.js)performs the compilation of the templates from main.bundle.js. This is called Just-in-Time (JiT) compilation. This term means that the compilation happens in time of the arrival of the bundles to the browser.

The drawbacks of the JIT compilation are:

1. There is a time gap between the loading bundles and rendering the UI. This time is spent on JiT compilation. On a small app like Hello CLI this time is minimal, but in real world apps, the JiT compilation can take a couple of seconds, so the user needs to wait longer for just seeing your app.

2. The Angular compiler has to be included in the vendor.bundle.js, which adds to the size of your app.

Using the JiT compilation in the prod is discouraged, and we want the templates to be pre-compiled into JavaScript before the bundles are created. This is what Ahead-of-Time (AoT) compilation is about.

The advantages of the AoT compilation are:

1. The browser can render the UI as soon as you app is loaded. There is no need to wait for code compilation.

2. The ngc compiler is not included in the vendor.bundle.js and the resulting size of your app might be smaller.

Why use the word “might” and not “will”? The removing of ngc compiler from the bundles should always result in smaller app size? Not always. The reason being that the compiled templates are larger than those that use a concise Angular syntax. The size of the Hello CLI will definitely be smaller as there is only one line to compile. But in larger apps with lots of views, the compiled templates may increase the size your app so it’s even larger than the JIT-compiled app with ngc included in the bundle. But you should use the AoT mode anyway because the user will see initial landing page of your app sooner.

Creating bundles with the -prod option

When you build the bundles with the -prod option, Angular CLI performs code optimization and AoT compilation. Let’s see it in action by running the following command in our Hello CLI project:

ng serve -prod

Open the app in your browser and check the Network tab as shown in the next image. Now the size of the same app is only 120KB (compare to 2.4MB) and the load time is 573 milliseconds (compare to 802 milliseconds).

https://yakovfain.files.wordpress.com/2017/08/ch1_size_aot1.png?w=150&h=109 150w, https://yakovfain.files.wordpress.com/2017/08/ch1_size_aot1.png?w=300&h=218 300w, https://yakovfain.files.wordpress.com/2017/08/ch1_size_aot1.png?w=768&h=557 768w, https://yakovfain.files.wordpress.com/2017/08/ch1_size_aot1.png?w=1024&h... 1024w, https://yakovfain.files.wordpress.com/2017/08/ch1_size_aot1.png 1094w" sizes="(max-width: 760px) 100vw, 760px" />

What a great result! As a matter of fact, the size of the app could be reduced even more after applying the gzip compression to the bundles. Note that the file names of the bundles now include a hash code of each bundle. Angular CLI calculates a new hash code on each prod build to prevent browsers from using the cached version if a new app version is deployed in prod.

Shouldn’t we always use AoT? Ideally, you should unless you use some third-party JavaScript libraries which produce errors during the AoT compilation. If you run into this problem, turn the AoT compilation off by building the bundles with the following command:

ng serve -prod -aot=false

The next screen shot shows that both the size and the load time increased compared to the AoT compiled app.

https://yakovfain.files.wordpress.com/2017/08/ch1_size_no_aot.png?w=150&... 150w, https://yakovfain.files.wordpress.com/2017/08/ch1_size_no_aot.png?w=300&... 300w, https://yakovfain.files.wordpress.com/2017/08/ch1_size_no_aot.png?w=768&... 768w, https://yakovfain.files.wordpress.com/2017/08/ch1_size_no_aot.png?w=1024... 1024w, https://yakovfain.files.wordpress.com/2017/08/ch1_size_no_aot.png 1126w" sizes="(max-width: 760px) 100vw, 760px" />

We were using the ng serve -prod command, which was building the bundles in memory. If you’re ready to generate prod files, use the ng build -prod command instead. We’ll go over the process of building production bundles and deploying the app on the server in chapter 8.

The goal of this section was to get you started with Angular CLI, and we’ll continue its coverage in chapter 2.

Read the original blog entry...

More Stories By Yakov Fain

Yakov Fain is a Java Champion and a co-founder of the IT consultancy Farata Systems and the product company SuranceBay. He wrote a thousand blogs (http://yakovfain.com) and several books about software development. Yakov authored and co-authored such books as "Angular 2 Development with TypeScript", "Java 24-Hour Trainer", and "Enterprise Web Development". His Twitter tag is @yfain