Bundling an Angular 2/4 app with AOT Compilation:
- Good knolwledge of Angular 2/4
- Basic knowledge of gulp.
Step 1 :
Ahead-of-Time Compilation or AOT Compilation:
JIT compilation incurs a runtime performance penalty. Views take longer to render because of the in-browser compilation step. The application is bigger because it includes the Angular compiler and a lot of library code that the application won’t actually need. Bigger apps take longer to transmit and are slower to load.
Also, while compiling at runtime on browser, all the template binding errors will occur on browser only.
Coming to the other and better option, AOT compilation.
AOT improves performance by compiling at build time and hence find template errors early as well.
Here are some advantages of AOT compilation
- Faster rendering
- Fewer asynchronous requests
- Smaller Angular framework download size
- Detect template errors earlier
- Better security
How to compile the app with ngc compiler :
We will use ngc compiler provided in the @angular/compiler-cli. To install it, run :
npm install @angular/compiler-cli @angular/platform-server --save
ngc requires its own tsconfig.json with AOT-oriented settings. We add tsconfig-aot.json with the following code :
“genDir” : specifies the directory for compiled code
“skipMetadataEmit” : true : property prevents the compiler from generating metadata files
To compile your code, run :
node_modules/.bin/ngc -p tsconfig-aot.json
What it does, is first creare ngFactory.ts files in dist/aot(specified in genDir) , then again transpiles it again to ngFactory.js using compilerOptions.
Note : JIT compilation also generates these same NgFactories in memory where they are largely invisible.
Now, instead of bootstrapping AppModule, we will bootstrapp the AppModuleNgFactory. Add boot-aot.ts, with the following code :
Note : In tsconfig.json, add boot-aot.ts to "exclude", so that it won't compile while you run your typescript compiler. Otherwise it will show error that, AppModuleNgFactory not found.
Step 2 :
A tree shaker walks the dependency graph, top to bottom, and shakes out unused code like dead leaves in a tree.
We are going to use a tree shaking utility called Rollup.
Rollup statically analyzes the application by following the trail of import and export statements. It produces a final code bundle that excludes code that is exported, but never imported. Rollup works on only ES2015, and that’s the reason we specified module as ES2015 in our tsconfig-aot.json.
Add the following dependencies :
npm install rollup rollup-plugin-node-resolve rollup-plugin-commonjs rollup-plugin-uglify --save-dev
Create a rollup-config.js and add the following code :
entry: the App entry point.
dest: this attribute tells Rollup to create a bundle called build.js in the dist folder.
format: Rollup supports several output formats. Since we’re running in the browser, we want to use an immediately-invoked function expression (IIFE).
For rollup, Run :
node_modules/.bin/rollup -c rollup-config.js
Step 3 :
Remove moduleId : module.id :
In Angular, for each component we add some metadata to it, one of that is moduleId. By specifying moduleId, we tell the component that its templates and styles are in the current folder. Since we compiled the bundle with aot, all the templates and css gets inlined to the js files, so we need to remove the moduleId property.
Add a new task in gulpfile, as follows :
Note : To install any gulp dependency, run the following command :
$ npm install --save-dev
Step 5 :
Vendor all assets :
Next we need to get assets from the development folder and put them corresponding to your production bundle. We will again use gulp for this.
Vendor css files
Add the following code in gulpfile.js
Vendor JS files
If you just want them to be copied, and not get concatenated, you can add the following code :
Similarly, we copy fonts and other assets that we need.
Step 5 :
Minify Images :
Next we will minify all our images used in the website. Here’s the gulp code :
Step 6 :
Change your index.html name to index-jit.html, now this index-jit.html we will use for development. And add a new index.html file with same content. This index.html we will use in production mode.
Update your index.html as follows :
Remove this code :
And Add :
Since we have created the precompiled bundle that is ready to for browser, all we need it to include that, we no longer need systemjs.config.js to load our application. You can either just add a script tag to add your js bundle, or you can follow the above code to add your bundle which disable caching of your bundle on browser. Disabling cache is only required if you constantly change your Application.
Next we need to copy our index.html to our production folder, and add our vendor js and vendor css files to it.
Add the following gulp code :
Step 7 :
Copy remaining assets
Step 9 :
The 9th and final step is to compress your bundle and vendor js and vendor css. We will use gulp-gzip dependency for this.
Reference : https://angular.io/guide/aot-compiler