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.

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

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).

What a great result! Google home page weighs more than 200KB. 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.

Recently released Angular CLI 1.3.0 offers a new option –build-optimizer, which does a better job in eliminating unused code. Even in our simple app it reduced the size of this app to 111Kb. On larger apps the effect of this option can be even bigger. In one of our apps that uses Angular Material it reduced the app size from 290KB to 200KB (lots of dead code there?). The option –build-optimizer works with both ng serve and ng build commands.

ng serve -prod --build-optimizer

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.

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.

5 thoughts on “Angular CLI: dev and prod builds with JiT and AoT

  1. Thanks for nice explain.
    I was trying to build with Aot like ng build -prod (cli ver : 1.4.7)
    And I realised that I am using third-party module.

    You mentioned ‘some third-party JavaScript libraries which produce errors during the AoT compilation’.
    Is there no way to take benefit of Aot if I use third-party module?

    Thanks

  2. Thanks for a lot for this post, i had issues with some third party i was using on my AOT, but after shutting off the AOT, my app was able to run on production machine without errors.

Leave a comment