docs(cookbook - aot compiler) (#2161)
docs(cb-aot-compiler): new cookbook on AoT compiler
This commit is contained in:
parent
97736ad5ee
commit
6813ced018
|
@ -0,0 +1,25 @@
|
||||||
|
/// <reference path='../_protractor/e2e.d.ts' />
|
||||||
|
'use strict';
|
||||||
|
/* tslint:disable:quotemark */
|
||||||
|
describe('AOT Compilation', function () {
|
||||||
|
|
||||||
|
beforeAll(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load page and click button', function (done) {
|
||||||
|
let headingSelector = element.all(by.css('h1')).get(0);
|
||||||
|
expect(headingSelector.getText()).toEqual('My First Angular 2 App');
|
||||||
|
|
||||||
|
expect(element.all(by.xpath('//div[text()="Magneta"]')).get(0).isPresent()).toBe(true);
|
||||||
|
expect(element.all(by.xpath('//div[text()="Bombasto"]')).get(0).isPresent()).toBe(true);
|
||||||
|
expect(element.all(by.xpath('//div[text()="Magma"]')).get(0).isPresent()).toBe(true);
|
||||||
|
expect(element.all(by.xpath('//div[text()="Tornado"]')).get(0).isPresent()).toBe(true);
|
||||||
|
|
||||||
|
let toggleButton = element.all(by.css('button')).get(0);
|
||||||
|
toggleButton.click().then(function() {
|
||||||
|
expect(headingSelector.isPresent()).toBe(false);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,5 @@
|
||||||
|
**/*.ngfactory.ts
|
||||||
|
**/*.metadata.json
|
||||||
|
dist
|
||||||
|
!app/tsconfig.json
|
||||||
|
!rollup.js
|
|
@ -0,0 +1,7 @@
|
||||||
|
<!-- #docregion -->
|
||||||
|
<button (click)="toggleHeading()">Toggle Heading</button>
|
||||||
|
<h1 *ngIf="showHeading">My First Angular 2 App</h1>
|
||||||
|
|
||||||
|
<h3>List of Heroes</h3>
|
||||||
|
<div *ngFor="let hero of heroes">{{hero}}</div>
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
// #docregion
|
||||||
|
// #docregion
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-app',
|
||||||
|
templateUrl: 'app.component.html'
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
showHeading = true;
|
||||||
|
heroes = ['Magneta', 'Bombasto', 'Magma', 'Tornado'];
|
||||||
|
|
||||||
|
toggleHeading() {
|
||||||
|
this.showHeading = !this.showHeading;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
// #docregion
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [ BrowserModule ],
|
||||||
|
declarations: [ AppComponent ],
|
||||||
|
bootstrap: [ AppComponent ]
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
|
@ -0,0 +1,6 @@
|
||||||
|
// #docregion
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
|
import { AppModule } from './app.module';
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule);
|
|
@ -0,0 +1,6 @@
|
||||||
|
// #docregion
|
||||||
|
import { platformBrowser } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
import { AppModuleNgFactory } from '../aot/app/app.module.ngfactory';
|
||||||
|
|
||||||
|
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"build": "build:aot",
|
||||||
|
"run": "http-server:e2e"
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!-- #docregion -->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Ahead of time compilation</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
|
||||||
|
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||||
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
|
<script src="node_modules/reflect-metadata/Reflect.js"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<!-- #docregion bundle -->
|
||||||
|
<body>
|
||||||
|
<my-app>Loading...</my-app>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script src="dist/build.js"></script>
|
||||||
|
<!-- #enddocregion bundle -->
|
||||||
|
</html>
|
|
@ -0,0 +1,25 @@
|
||||||
|
// #docregion
|
||||||
|
import rollup from 'rollup'
|
||||||
|
import nodeResolve from 'rollup-plugin-node-resolve'
|
||||||
|
import commonjs from 'rollup-plugin-commonjs';
|
||||||
|
import uglify from 'rollup-plugin-uglify'
|
||||||
|
|
||||||
|
// #docregion config
|
||||||
|
export default {
|
||||||
|
entry: 'app/main.js',
|
||||||
|
dest: 'dist/build.js', // output a single application bundle
|
||||||
|
sourceMap: false,
|
||||||
|
format: 'iife',
|
||||||
|
plugins: [
|
||||||
|
nodeResolve({jsnext: true, module: true}),
|
||||||
|
// #docregion commonjs
|
||||||
|
commonjs({
|
||||||
|
include: 'node_modules/rxjs/**',
|
||||||
|
}),
|
||||||
|
// #enddocregion commonjs
|
||||||
|
// #docregion uglify
|
||||||
|
uglify()
|
||||||
|
// #enddocregion uglify
|
||||||
|
]
|
||||||
|
}
|
||||||
|
// #enddocregion config
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"module": "es2015",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"sourceMap": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"removeComments": false,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"suppressImplicitAnyIndexErrors": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"files": [
|
||||||
|
"app/app.module.ts",
|
||||||
|
"app/main.ts",
|
||||||
|
"./typings/index.d.ts"
|
||||||
|
],
|
||||||
|
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"genDir": "aot",
|
||||||
|
"skipMetadataEmit" : true
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,7 +19,8 @@
|
||||||
"start:webpack": "webpack-dev-server --inline --progress --port 8080",
|
"start:webpack": "webpack-dev-server --inline --progress --port 8080",
|
||||||
"test:webpack": "karma start karma.webpack.conf.js",
|
"test:webpack": "karma start karma.webpack.conf.js",
|
||||||
"build:webpack": "rimraf dist && webpack --config config/webpack.prod.js --bail",
|
"build:webpack": "rimraf dist && webpack --config config/webpack.prod.js --bail",
|
||||||
"build:cli": "ng build"
|
"build:cli": "ng build",
|
||||||
|
"build:aot": "ngc -p tsconfig-aot.json && rollup -c rollup.js"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
|
@ -33,12 +34,16 @@
|
||||||
"@angular/http": "2.0.0-rc.7",
|
"@angular/http": "2.0.0-rc.7",
|
||||||
"@angular/platform-browser": "2.0.0-rc.7",
|
"@angular/platform-browser": "2.0.0-rc.7",
|
||||||
"@angular/platform-browser-dynamic": "2.0.0-rc.7",
|
"@angular/platform-browser-dynamic": "2.0.0-rc.7",
|
||||||
|
"@angular/platform-server": "2.0.0-rc.7",
|
||||||
"@angular/router": "3.0.0-rc.3",
|
"@angular/router": "3.0.0-rc.3",
|
||||||
"@angular/upgrade": "2.0.0-rc.7",
|
"@angular/upgrade": "2.0.0-rc.7",
|
||||||
"angular2-in-memory-web-api": "0.0.19",
|
"angular2-in-memory-web-api": "0.0.19",
|
||||||
"bootstrap": "^3.3.6",
|
"bootstrap": "^3.3.6",
|
||||||
"core-js": "^2.4.1",
|
"core-js": "^2.4.1",
|
||||||
"reflect-metadata": "^0.1.3",
|
"reflect-metadata": "^0.1.3",
|
||||||
|
"rollup": "^0.34.13",
|
||||||
|
"rollup-plugin-node-resolve": "^2.0.0",
|
||||||
|
"rollup-plugin-uglify": "^1.0.1",
|
||||||
"rxjs": "5.0.0-beta.12",
|
"rxjs": "5.0.0-beta.12",
|
||||||
"systemjs": "0.19.27",
|
"systemjs": "0.19.27",
|
||||||
"zone.js": "^0.6.21"
|
"zone.js": "^0.6.21"
|
||||||
|
@ -71,11 +76,12 @@
|
||||||
"protractor": "^3.3.0",
|
"protractor": "^3.3.0",
|
||||||
"raw-loader": "^0.5.1",
|
"raw-loader": "^0.5.1",
|
||||||
"rimraf": "^2.5.2",
|
"rimraf": "^2.5.2",
|
||||||
|
"rollup-plugin-commonjs": "^4.1.0",
|
||||||
"style-loader": "^0.13.1",
|
"style-loader": "^0.13.1",
|
||||||
"ts-loader": "^0.8.2",
|
"ts-loader": "^0.8.2",
|
||||||
"ts-node": "^0.7.3",
|
"ts-node": "^0.7.3",
|
||||||
"tslint": "^3.15.1",
|
"tslint": "^3.15.1",
|
||||||
"typescript": "^1.8.10",
|
"typescript": "2.0.2",
|
||||||
"typings": "^1.3.2",
|
"typings": "^1.3.2",
|
||||||
"webpack": "^1.13.0",
|
"webpack": "^1.13.0",
|
||||||
"webpack-dev-server": "^1.14.1",
|
"webpack-dev-server": "^1.14.1",
|
||||||
|
|
|
@ -5,6 +5,11 @@
|
||||||
"description": "A collection of recipes for common Angular application scenarios"
|
"description": "A collection of recipes for common Angular application scenarios"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"aot-compiler": {
|
||||||
|
"title": "Ahead of Time Compiler",
|
||||||
|
"intro": "Learn how to use the Ahead of Time Compiler"
|
||||||
|
},
|
||||||
|
|
||||||
"a1-a2-quick-reference": {
|
"a1-a2-quick-reference": {
|
||||||
"title": "Angular 1 to 2 Quick Reference",
|
"title": "Angular 1 to 2 Quick Reference",
|
||||||
"navTitle": "Angular 1 to 2 Quick Ref",
|
"navTitle": "Angular 1 to 2 Quick Ref",
|
||||||
|
|
|
@ -0,0 +1,303 @@
|
||||||
|
include ../_util-fns
|
||||||
|
|
||||||
|
:marked
|
||||||
|
This cookbook describes how to radically improve performance by compiling _Ahead of Time_ (AoT)
|
||||||
|
during a build process.
|
||||||
|
|
||||||
|
a#toc
|
||||||
|
:marked
|
||||||
|
## Table of Contents
|
||||||
|
* [Overview](#overview)
|
||||||
|
* [_Ahead-of-Time_ vs _Just-in-Time_](#aot-jit)
|
||||||
|
* [Compile with AoT](#compile)
|
||||||
|
* [Bootstrap](#bootstrap)
|
||||||
|
* [Tree Shaking](#tree-shaking)
|
||||||
|
* [Load the bundle](#load)
|
||||||
|
* [Serve the app](#serve)
|
||||||
|
* [Source Code](#source-code)
|
||||||
|
|
||||||
|
a#overview
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## Overview
|
||||||
|
Angular component templates consist of a mix of standard html and Angular syntax (e.g. `ngIf`, `ngFor`).
|
||||||
|
|
||||||
|
Expressions like `ngIf` and `ngFor` are specific to Angular. The browser cannot execute them directly.
|
||||||
|
|
||||||
|
Before the browser can render the application, Angular components and their templates must be converted to executable JavaScript.
|
||||||
|
We refer to this step as _Angular compilation_ or just plain _compilation_.
|
||||||
|
|
||||||
|
You can compile the app in the browser, at runtime, as the application loads, using the _Just-in-Time_ (JiT) compiler.
|
||||||
|
This is the standard development approach shown throughout the documentation.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
This cookbook describes how to improve performance by compiling at build time instead,
|
||||||
|
using a process called _Ahead-of-Time_ compilation (AoT).
|
||||||
|
|
||||||
|
|
||||||
|
a#aot-jit
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## _Ahead-of-time_ (AoT) vs _Just-in-time_ (JiT)
|
||||||
|
|
||||||
|
There is actually only one Angular compiler. The difference between AoT and JiT is a matter of timing and tooling.
|
||||||
|
With AoT, the compiler runs once at build time using one set of libraries;
|
||||||
|
With JiT it runs every time for every user at runtime using a different set of libraries.
|
||||||
|
|
||||||
|
### Why do AoT compilation?
|
||||||
|
|
||||||
|
The performance improvement from doing AoT compilation can be significant for three reasons:
|
||||||
|
|
||||||
|
*Faster rendering*
|
||||||
|
|
||||||
|
With AoT, the browser downloads a pre-compiled version of the application.
|
||||||
|
The browser loads executable code so it can render the application immediately, without waiting to compile the app first.
|
||||||
|
|
||||||
|
*Fewer asynchronous requests*
|
||||||
|
|
||||||
|
The compiler _inlines_ external html templates and css style sheets within the application JavaScript,
|
||||||
|
eliminating separate ajax requests for those source files.
|
||||||
|
|
||||||
|
*Smaller Angular framework download size*
|
||||||
|
|
||||||
|
There's no need to download the Angular compiler if the app is already compiled.
|
||||||
|
The compiler is roughly half of Angular itself, so omitting it dramatically reduces the application payload.
|
||||||
|
|
||||||
|
a#compile
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## Compile with AoT
|
||||||
|
|
||||||
|
### Prepare for offline compilation
|
||||||
|
|
||||||
|
This cookbook takes the <a href='/docs/ts/latest/quickstart.html'>QuickStart</a> as its starting point.
|
||||||
|
A few minor changes to the lone `app.component` lead to these two class and html files:
|
||||||
|
|
||||||
|
+makeTabs(
|
||||||
|
`cb-aot-compiler/ts/app/app.component.html,
|
||||||
|
cb-aot-compiler/ts/app/app.component.ts`,
|
||||||
|
null,
|
||||||
|
`app/app.component.html,
|
||||||
|
app/app.component.ts`
|
||||||
|
)
|
||||||
|
|
||||||
|
:marked
|
||||||
|
Install a few new npm dependencies with the following command:
|
||||||
|
code-example(format='.').
|
||||||
|
npm install @angular/compiler-cli @angular/platform-server typescript@2.0.2 --save
|
||||||
|
:marked
|
||||||
|
You will run the `ngc` compiler provided in the `@angular/compiler-cli` npm package
|
||||||
|
instead of the TypeScript compiler (`tsc`).
|
||||||
|
|
||||||
|
`ngc` is a drop-in replacement for `tsc` and is configured much the same way.
|
||||||
|
|
||||||
|
`ngc` requires its own `tsconfig.json` with AoT-oriented settings.
|
||||||
|
Copy the original `tsconfig.json` to a file called `tsconfig-aot.json`, then modify it to look as follows.
|
||||||
|
|
||||||
|
+makeExample('cb-aot-compiler/ts/tsconfig-aot.json', null, 'tsconfig-aot.json')(format='.')
|
||||||
|
|
||||||
|
:marked
|
||||||
|
The `compilerOptions` section is unchanged except for one property.
|
||||||
|
**Set the `module` to `es2015`**.
|
||||||
|
This is important as explained later in the [Tree Shaking](#tree-shaking) section.
|
||||||
|
|
||||||
|
What's really new is the `ngc` section at the bottom called `angularCompilerOptions`.
|
||||||
|
Its `"genDir"` property tells the compiler
|
||||||
|
to store the compiled output files in a new `aot` folder.
|
||||||
|
|
||||||
|
The `"skipMetadataEmit" : true` property prevents the compiler from generating metadata files with the compiled application.
|
||||||
|
Metadata files are not necessary when targeting TypeScript files, so there is no reason to include them.
|
||||||
|
|
||||||
|
### Compiling the application
|
||||||
|
|
||||||
|
Initiate AoT compilation from the command line using the previously installed `ngc` compiler by executing:
|
||||||
|
code-example(format='.').
|
||||||
|
node_modules/.bin/ngc -p tsconfig-aot.json
|
||||||
|
:marked
|
||||||
|
`ngc` expects the `-p` switch to point to a `tsconfig.json` file or a folder containing a `tsconfig.json` file.
|
||||||
|
|
||||||
|
After `ngc` completes, look for a collection of _NgFactory_ files in the `aot` folder (the folder specified as `genDir` in `tsconfig-aot.json`).
|
||||||
|
|
||||||
|
These factory files are essential to the compiled application.
|
||||||
|
Each component factory creates an instance of the component at runtime by combining the original class file
|
||||||
|
and a JavaScript representation of the component's template.
|
||||||
|
Note that the original component class is still referenced internally by the generated factory.
|
||||||
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
The curious can open the `aot/app.component.ngfactory.ts` to see the original Angular template syntax
|
||||||
|
in its intermediate, compiled-to-TypeScript form.
|
||||||
|
|
||||||
|
JiT compilation generates these same _NgFactories_ in memory where they are largely invisible.
|
||||||
|
AoT compilation reveals them as separate, physical files.
|
||||||
|
|
||||||
|
:marked
|
||||||
|
.alert.is-important
|
||||||
|
:marked
|
||||||
|
Do not edit the _NgFactories_! Re-compilation replaces these files and all edits will be lost.
|
||||||
|
|
||||||
|
a#bootstrap
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## Bootstrap
|
||||||
|
|
||||||
|
The AoT path changes application bootstrapping.
|
||||||
|
|
||||||
|
Instead of bootstrapping `AppModule`, you bootstrap the application with the generated module factory, `AppModuleNgFactory`.
|
||||||
|
|
||||||
|
Switch from the `platformBrowserDynamic.bootstrap` used in JiT compilation to
|
||||||
|
`platformBrowser().bootstrapModuleFactory` and pass in the `AppModuleNgFactory`.
|
||||||
|
|
||||||
|
Here is AoT bootstrap in `main.ts` next to the familiar JiT version:
|
||||||
|
|
||||||
|
+makeTabs(
|
||||||
|
`cb-aot-compiler/ts/app/main.ts,
|
||||||
|
cb-aot-compiler/ts/app/main-jit.ts`,
|
||||||
|
null,
|
||||||
|
`app/main.ts (AoT),
|
||||||
|
app/main.ts (JiT)`
|
||||||
|
)
|
||||||
|
|
||||||
|
:marked
|
||||||
|
Be sure to recompile with `ngc`!
|
||||||
|
|
||||||
|
a#tree-shaking
|
||||||
|
:marked
|
||||||
|
## Tree Shaking
|
||||||
|
|
||||||
|
AoT compilation sets the stage for further optimization through a process called _Tree Shaking_.
|
||||||
|
A Tree Shaker walks the dependency graph, top to bottom, and _shakes out_ unused code like
|
||||||
|
dead needles in a Christmas tree.
|
||||||
|
|
||||||
|
Tree Shaking can greatly reduce the downloaded size of the application
|
||||||
|
by removing unused portions of both source and library code.
|
||||||
|
In fact, most of the reduction in small apps comes from removing unreferenced Angular features.
|
||||||
|
|
||||||
|
For example, this demo application doesn't use anything from the `@angular/forms` library.
|
||||||
|
There is no reason to download Forms-related Angular code and tree shaking ensures that you don't.
|
||||||
|
|
||||||
|
Tree Shaking and AoT compilation are separate steps.
|
||||||
|
Tree Shaking can only target JavaScript code.
|
||||||
|
AoT compilation converts more of the application to JavaScript,
|
||||||
|
which in turn makes more of the application "Tree Shakable".
|
||||||
|
|
||||||
|
### Rollup
|
||||||
|
|
||||||
|
This cookbook illustrates 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 can only Tree Shake `ES2015` modules which have `import` and `export` statements.
|
||||||
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
Recall that `tsconfig-aot.json` is configured to produce `ES2015` modules.
|
||||||
|
It's not important that the code itself be written with `ES2015` syntax such as `class` and `const`.
|
||||||
|
What matters is that the code uses ES `import` and `export` statements rather than `require` statements.
|
||||||
|
:marked
|
||||||
|
Install the Rollup dependencies with this command:
|
||||||
|
code-example(format='.').
|
||||||
|
npm install rollup rollup-plugin-node-resolve rollup-plugin-commonjs rollup-plugin-uglify --save-dev
|
||||||
|
:marked
|
||||||
|
Next, create a configuration file to tell Rollup how to process the application.
|
||||||
|
The configuration file in this cookbook is named `rollup.js` and looks like this.
|
||||||
|
|
||||||
|
+makeExample('cb-aot-compiler/ts/rollup.js', null, 'rollup.js')(format='.')
|
||||||
|
:marked
|
||||||
|
It tells Rollup that the app entry point is `app/main.js` .
|
||||||
|
The `dest` attribute tells Rollup to create a bundle called `build.js` in the `dist` folder.
|
||||||
|
Then there are plugins.
|
||||||
|
|
||||||
|
:marked
|
||||||
|
### Rollup Plugins
|
||||||
|
|
||||||
|
Optional plugins filter and transform the Rollup inputs and output.
|
||||||
|
|
||||||
|
*RxJS*
|
||||||
|
Rollup expects application source code to use `ES2015` modules.
|
||||||
|
Not all external dependencies are published as `ES2015` modules.
|
||||||
|
In fact, most are not. Many of them are published as _CommonJS_ modules.
|
||||||
|
|
||||||
|
The _RxJs_ observable library is an essential Angular dependency published as an ES5 JavaScript _CommonJS_ module.
|
||||||
|
|
||||||
|
Luckily there is a Rollup plugin that modifies _RxJs_
|
||||||
|
to use the ES `import` and `export` statements that Rollup requires.
|
||||||
|
Rollup then preserves in the final bundle the parts of `RxJS` referenced by the application.
|
||||||
|
|
||||||
|
+makeExample('cb-aot-compiler/ts/rollup.js','commonjs','rollup.js (CommonJs to ES2015 Plugin)')(format='.')
|
||||||
|
|
||||||
|
:marked
|
||||||
|
*Minification*
|
||||||
|
|
||||||
|
Rollup Tree Shaking reduces code size considerably. Minification makes it smaller still.
|
||||||
|
This cookbook relies on the _uglify_ Rollup plugin to minify and mangle the code.
|
||||||
|
|
||||||
|
+makeExample('cb-aot-compiler/ts/rollup.js','uglify','rollup.js (CommonJs to ES2015 Plugin)')(format='.')
|
||||||
|
|
||||||
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
In a production setting, you would also enable gzip on the web server to compress
|
||||||
|
the code into an even smaller package going over the wire.
|
||||||
|
|
||||||
|
:marked
|
||||||
|
### Run Rollup
|
||||||
|
Execute the Rollup process with this command:
|
||||||
|
code-example(format='.').
|
||||||
|
node_modules/.bin/rollup -c rollup.js
|
||||||
|
|
||||||
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
Rollup may log many lines with the following warning message:
|
||||||
|
code-example(format='.', language='bash').
|
||||||
|
The `this` keyword is equivalent to `undefined` at the top level of an ES module, and has been rewritten
|
||||||
|
:marked
|
||||||
|
You can safely ignore these warnings.
|
||||||
|
|
||||||
|
a#load
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## Load the Bundle
|
||||||
|
|
||||||
|
Loading the generated application bundle does not require a module loader like SystemJS.
|
||||||
|
Remove the scripts that concern SystemJS.
|
||||||
|
Instead, load the bundle file using a single `script` tag:
|
||||||
|
|
||||||
|
+makeExample('cb-aot-compiler/ts/index.html','bundle','index.html (load bundle)')(format='.')
|
||||||
|
|
||||||
|
a#serve
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## Serve the app
|
||||||
|
|
||||||
|
You'll need a web server to host the application.
|
||||||
|
Use the same _Lite Server_ employed elsewhere in the documentation:
|
||||||
|
code-example(format='.').
|
||||||
|
npm run lite
|
||||||
|
:marked
|
||||||
|
The server starts, launches a browser, and the app should appear.
|
||||||
|
|
||||||
|
a#source-code
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## Source Code
|
||||||
|
|
||||||
|
Here is the pertinent AoT source code for this cookbook:
|
||||||
|
+makeTabs(
|
||||||
|
`cb-aot-compiler/ts/app/app.component.html,
|
||||||
|
cb-aot-compiler/ts/app/app.component.ts,
|
||||||
|
cb-aot-compiler/ts/app/main.ts,
|
||||||
|
cb-aot-compiler/ts/index.html,
|
||||||
|
cb-aot-compiler/ts/tsconfig-aot.json,
|
||||||
|
cb-aot-compiler/ts/rollup.js`,
|
||||||
|
null,
|
||||||
|
`app/app.component.html,
|
||||||
|
app/app.component.ts,
|
||||||
|
app/main.ts,
|
||||||
|
index.html,
|
||||||
|
tsconfig-aot.json,
|
||||||
|
rollup.js`
|
||||||
|
)
|
Loading…
Reference in New Issue