docs(toh-6-aot): add aot to toh-6 (#2496)
* docs(toh-6-aot): add aot to toh-6 s s s s s * docs(toh-6-aot): add aot to toh-6 * docs(toh-6-aot): make aot e2e tests run in the same project Updates tooling for this purpose and also the prose.
This commit is contained in:
parent
2e17d587de
commit
cdfe957ab8
23
gulpfile.js
23
gulpfile.js
|
@ -296,7 +296,12 @@ function runE2eTsTests(appDir, outputFile) {
|
||||||
var appBuildSpawnInfo = spawnExt('npm', ['run', config.build], { cwd: appDir });
|
var appBuildSpawnInfo = spawnExt('npm', ['run', config.build], { cwd: appDir });
|
||||||
var appRunSpawnInfo = spawnExt('npm', ['run', config.run, '--', '-s'], { cwd: appDir });
|
var appRunSpawnInfo = spawnExt('npm', ['run', config.run, '--', '-s'], { cwd: appDir });
|
||||||
|
|
||||||
return runProtractor(appBuildSpawnInfo.promise, appDir, appRunSpawnInfo, outputFile);
|
var run = runProtractor(appBuildSpawnInfo.promise, appDir, appRunSpawnInfo, outputFile);
|
||||||
|
|
||||||
|
if (fs.existsSync(appDir + '/aot/index.html')) {
|
||||||
|
run = run.then(() => runProtractorAoT(appDir, outputFile));
|
||||||
|
}
|
||||||
|
return run;
|
||||||
}
|
}
|
||||||
|
|
||||||
function runProtractor(prepPromise, appDir, appRunSpawnInfo, outputFile) {
|
function runProtractor(prepPromise, appDir, appRunSpawnInfo, outputFile) {
|
||||||
|
@ -341,6 +346,20 @@ function runProtractor(prepPromise, appDir, appRunSpawnInfo, outputFile) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function runProtractorAoT(appDir, outputFile) {
|
||||||
|
fs.appendFileSync(outputFile, '++ AoT version ++\n');
|
||||||
|
var aotBuildSpawnInfo = spawnExt('npm', ['run', 'build:aot'], { cwd: appDir });
|
||||||
|
var promise = aotBuildSpawnInfo.promise;
|
||||||
|
|
||||||
|
var copyFileCmd = 'copy-dist-files.js';
|
||||||
|
if (fs.existsSync(appDir + '/' + copyFileCmd)) {
|
||||||
|
promise = promise.then(() =>
|
||||||
|
spawnExt('node', [copyFileCmd], { cwd: appDir }).promise );
|
||||||
|
}
|
||||||
|
var aotRunSpawnInfo = spawnExt('npm', ['run', 'http-server:e2e', 'aot', '--', '-s'], { cwd: appDir });
|
||||||
|
return runProtractor(promise, appDir, aotRunSpawnInfo, outputFile);
|
||||||
|
}
|
||||||
|
|
||||||
// start the server in appDir/build/web; then run protractor with the specified
|
// start the server in appDir/build/web; then run protractor with the specified
|
||||||
// fileName; then shut down the example. All protractor output is appended
|
// fileName; then shut down the example. All protractor output is appended
|
||||||
// to the outputFile.
|
// to the outputFile.
|
||||||
|
@ -883,7 +902,7 @@ function harpCompile() {
|
||||||
gutil.log("NODE_ENV: " + process.env.NODE_ENV);
|
gutil.log("NODE_ENV: " + process.env.NODE_ENV);
|
||||||
|
|
||||||
if(argv.page) harpJsonSetJade2NgTo(true);
|
if(argv.page) harpJsonSetJade2NgTo(true);
|
||||||
|
|
||||||
if(skipLangs && fs.existsSync(WWW) && backupApiHtmlFilesExist(WWW)) {
|
if(skipLangs && fs.existsSync(WWW) && backupApiHtmlFilesExist(WWW)) {
|
||||||
gutil.log(`Harp site recompile: skipping recompilation of API docs for [${skipLangs}]`);
|
gutil.log(`Harp site recompile: skipping recompilation of API docs for [${skipLangs}]`);
|
||||||
gutil.log(`API docs will be copied from existing ${WWW} folder.`)
|
gutil.log(`API docs will be copied from existing ${WWW} folder.`)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"http-server:e2e": "http-server",
|
"http-server:e2e": "http-server",
|
||||||
"http-server:cli": "http-server dist/",
|
"http-server:cli": "http-server dist/",
|
||||||
"lite": "lite-server",
|
"lite": "lite-server",
|
||||||
|
"lite:aot": "lite-server -c aot/bs-config.json",
|
||||||
"postinstall": "typings install",
|
"postinstall": "typings install",
|
||||||
"test": "tsc && concurrently \"tsc -w\" \"karma start karma.conf.js\"",
|
"test": "tsc && concurrently \"tsc -w\" \"karma start karma.conf.js\"",
|
||||||
"tsc": "tsc",
|
"tsc": "tsc",
|
||||||
|
@ -17,7 +18,8 @@
|
||||||
"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",
|
"build:aot": "ngc -p tsconfig-aot.json && rollup -c rollup-config.js",
|
||||||
|
"copy-dist-files": "node ./copy-dist-files.js",
|
||||||
"i18n": "ng-xi18n"
|
"i18n": "ng-xi18n"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
|
|
|
@ -10,5 +10,9 @@
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"suppressImplicitAnyIndexErrors": true,
|
"suppressImplicitAnyIndexErrors": true,
|
||||||
"types": []
|
"types": []
|
||||||
}
|
},
|
||||||
|
"exclude": [
|
||||||
|
"node_modules/*",
|
||||||
|
"**/*-aot.ts"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,4 +2,4 @@
|
||||||
**/*.metadata.json
|
**/*.metadata.json
|
||||||
dist
|
dist
|
||||||
!app/tsconfig.json
|
!app/tsconfig.json
|
||||||
!rollup.js
|
!rollup-config.js
|
|
@ -13,5 +13,4 @@ export class AppComponent {
|
||||||
toggleHeading() {
|
toggleHeading() {
|
||||||
this.showHeading = !this.showHeading;
|
this.showHeading = !this.showHeading;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<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/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/reflect-metadata/Reflect.js"></script>
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
"raw-loader": "^0.5.1",
|
"raw-loader": "^0.5.1",
|
||||||
"rimraf": "^2.5.4",
|
"rimraf": "^2.5.4",
|
||||||
"rollup-plugin-commonjs": "^4.1.0",
|
"rollup-plugin-commonjs": "^4.1.0",
|
||||||
|
"source-map-explorer": "^1.3.2",
|
||||||
"style-loader": "^0.13.1",
|
"style-loader": "^0.13.1",
|
||||||
"ts-loader": "^0.8.2",
|
"ts-loader": "^0.8.2",
|
||||||
"ts-node": "^1.3.0",
|
"ts-node": "^1.3.0",
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
**/*.js
|
**/*.js
|
||||||
|
aot/**/*.ts
|
||||||
|
!rollup-config.js
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"port": 8000,
|
||||||
|
"files": ["./aot/**/*.{html,htm,css,js}"],
|
||||||
|
"server": { "baseDir": "./aot" }
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!-- #docregion -->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<base href="/">
|
||||||
|
<title>Angular Tour of Heroes</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<script src="shim.min.js"></script>
|
||||||
|
<script src="zone.min.js"></script>
|
||||||
|
<!-- #docregion moduleId -->
|
||||||
|
<script>window.module = 'aot';</script>
|
||||||
|
<!-- #enddocregion moduleId -->
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<my-app>Loading...</my-app>
|
||||||
|
</body>
|
||||||
|
<script src="dist/build.js"></script>
|
||||||
|
</html>
|
|
@ -5,7 +5,6 @@ import { Component } from '@angular/core';
|
||||||
@Component({
|
@Component({
|
||||||
moduleId: module.id,
|
moduleId: module.id,
|
||||||
selector: 'my-app',
|
selector: 'my-app',
|
||||||
|
|
||||||
template: `
|
template: `
|
||||||
<h1>{{title}}</h1>
|
<h1>{{title}}</h1>
|
||||||
<nav>
|
<nav>
|
||||||
|
|
|
@ -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,11 @@
|
||||||
|
// #docregion
|
||||||
|
var fs = require('fs');
|
||||||
|
var resources = [
|
||||||
|
'node_modules/core-js/client/shim.min.js',
|
||||||
|
'node_modules/zone.js/dist/zone.min.js'
|
||||||
|
];
|
||||||
|
resources.map(function(f) {
|
||||||
|
var path = f.split('/');
|
||||||
|
var t = 'aot/' + path[path.length-1];
|
||||||
|
fs.createReadStream(f).pipe(fs.createWriteStream(t));
|
||||||
|
});
|
|
@ -1,3 +1,4 @@
|
||||||
|
<!-- #docregion -->
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
// #docregion
|
||||||
|
import rollup from 'rollup'
|
||||||
|
import nodeResolve from 'rollup-plugin-node-resolve'
|
||||||
|
import commonjs from 'rollup-plugin-commonjs';
|
||||||
|
import uglify from 'rollup-plugin-uglify'
|
||||||
|
|
||||||
|
//paths are relative to the execution path
|
||||||
|
export default {
|
||||||
|
entry: 'app/main-aot.js',
|
||||||
|
dest: 'aot/dist/build.js', // output a single application bundle
|
||||||
|
sourceMap: true,
|
||||||
|
sourceMapFile: 'aot/dist/build.js.map',
|
||||||
|
format: 'iife',
|
||||||
|
plugins: [
|
||||||
|
nodeResolve({jsnext: true, module: true}),
|
||||||
|
commonjs({
|
||||||
|
include: [
|
||||||
|
'node_modules/rxjs/**',
|
||||||
|
'node_modules/angular-in-memory-web-api/**'
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
uglify()
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"module": "es2015",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"sourceMap": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"removeComments": false,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"suppressImplicitAnyIndexErrors": true,
|
||||||
|
"types": []
|
||||||
|
},
|
||||||
|
|
||||||
|
"files": [
|
||||||
|
"app/app.module.ts",
|
||||||
|
"app/main-aot.ts",
|
||||||
|
"typings/index.d.ts"
|
||||||
|
],
|
||||||
|
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"genDir": "aot",
|
||||||
|
"skipMetadataEmit" : true
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,4 +21,4 @@
|
||||||
"include": [
|
"include": [
|
||||||
"*/e2e-spec.ts"
|
"*/e2e-spec.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,20 +15,23 @@ a#toc
|
||||||
* [Load the bundle](#load)
|
* [Load the bundle](#load)
|
||||||
* [Serve the app](#serve)
|
* [Serve the app](#serve)
|
||||||
* [Source Code](#source-code)
|
* [Source Code](#source-code)
|
||||||
|
* [Tour of Heroes](#toh)
|
||||||
|
|
||||||
a#overview
|
a#overview
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Overview
|
## 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.
|
An Angular application consist largely of components and their HTML templates.
|
||||||
|
Before the browser can render the application,
|
||||||
|
the components and templates must be converted to executable JavaScript by the _Angular compiler_.
|
||||||
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
<a href="https://www.youtube.com/watch?v=kW9cJsvcsGo" target="_blank">Watch compiler author Tobias Bosch explain the Angular Compiler</a> at AngularConnect 2016.
|
||||||
|
:marked
|
||||||
|
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.
|
This is the standard development approach shown throughout the documentation.
|
||||||
|
It's great .. but it has shortcomings.
|
||||||
|
|
||||||
JiT compilation incurs a runtime performance penalty.
|
JiT compilation incurs a runtime performance penalty.
|
||||||
Views take longer to render because of the in-browser compilation step.
|
Views take longer to render because of the in-browser compilation step.
|
||||||
|
@ -36,8 +39,11 @@ a#overview
|
||||||
and a lot of library code that the application won't actually need.
|
and a lot of library code that the application won't actually need.
|
||||||
Bigger apps take longer to transmit and are slower to load.
|
Bigger apps take longer to transmit and are slower to load.
|
||||||
|
|
||||||
This cookbook describes how to improve performance by compiling at build time instead,
|
Compilation can uncover many component-template binding errors.
|
||||||
using a process called _Ahead-of-Time_ compilation (AoT).
|
JiT compilation discovers them at runtime which is later than we'd like.
|
||||||
|
|
||||||
|
The **_Ahead-of-Time_ (AoT) compiler** can catch template errors early and improve performance
|
||||||
|
by compiling at build time as you'll learn in this chapter.
|
||||||
|
|
||||||
|
|
||||||
a#aot-jit
|
a#aot-jit
|
||||||
|
@ -51,8 +57,6 @@ a#aot-jit
|
||||||
|
|
||||||
### Why do AoT compilation?
|
### Why do AoT compilation?
|
||||||
|
|
||||||
The performance improvement from doing AoT compilation can be significant for three reasons:
|
|
||||||
|
|
||||||
*Faster rendering*
|
*Faster rendering*
|
||||||
|
|
||||||
With AoT, the browser downloads a pre-compiled version of the application.
|
With AoT, the browser downloads a pre-compiled version of the application.
|
||||||
|
@ -68,6 +72,19 @@ a#aot-jit
|
||||||
There's no need to download the Angular compiler if the app is already compiled.
|
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.
|
The compiler is roughly half of Angular itself, so omitting it dramatically reduces the application payload.
|
||||||
|
|
||||||
|
|
||||||
|
*Detect template errors earlier*
|
||||||
|
|
||||||
|
The AoT compiler detects and reports template binding errors during the build step
|
||||||
|
before users can see them.
|
||||||
|
|
||||||
|
|
||||||
|
*Better security*
|
||||||
|
|
||||||
|
AoT compiles HTML templates and components into JavaScript files long before they are served to the client.
|
||||||
|
With no templates to read and no risky client-side HTML or JavaScript evaluation,
|
||||||
|
there are fewer opportunities for injection attacks.
|
||||||
|
|
||||||
a#compile
|
a#compile
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
|
@ -75,7 +92,7 @@ a#compile
|
||||||
|
|
||||||
### Prepare for offline compilation
|
### Prepare for offline compilation
|
||||||
|
|
||||||
This cookbook takes the <a href='/docs/ts/latest/quickstart.html'>QuickStart</a> as its starting point.
|
Take the <a href='/docs/ts/latest/quickstart.html'>QuickStart</a> as a starting point.
|
||||||
A few minor changes to the lone `app.component` lead to these two class and html files:
|
A few minor changes to the lone `app.component` lead to these two class and html files:
|
||||||
|
|
||||||
+makeTabs(
|
+makeTabs(
|
||||||
|
@ -84,7 +101,7 @@ a#compile
|
||||||
null,
|
null,
|
||||||
`app/app.component.html,
|
`app/app.component.html,
|
||||||
app/app.component.ts`
|
app/app.component.ts`
|
||||||
)
|
)(format='.')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
Install a few new npm dependencies with the following command:
|
Install a few new npm dependencies with the following command:
|
||||||
|
@ -118,6 +135,11 @@ code-example(format='.').
|
||||||
Initiate AoT compilation from the command line using the previously installed `ngc` compiler by executing:
|
Initiate AoT compilation from the command line using the previously installed `ngc` compiler by executing:
|
||||||
code-example(format='.').
|
code-example(format='.').
|
||||||
node_modules/.bin/ngc -p tsconfig-aot.json
|
node_modules/.bin/ngc -p tsconfig-aot.json
|
||||||
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
Windows users should surround the `ngc` command in double quotes:
|
||||||
|
code-example(format='.').
|
||||||
|
"node_modules/.bin/ngc" -p tsconfig-aot.json
|
||||||
:marked
|
:marked
|
||||||
`ngc` expects the `-p` switch to point to a `tsconfig.json` file or a folder containing a `tsconfig.json` file.
|
`ngc` expects the `-p` switch to point to a `tsconfig.json` file or a folder containing a `tsconfig.json` file.
|
||||||
|
|
||||||
|
@ -203,10 +225,11 @@ a#tree-shaking
|
||||||
code-example(format='.').
|
code-example(format='.').
|
||||||
npm install rollup rollup-plugin-node-resolve rollup-plugin-commonjs rollup-plugin-uglify --save-dev
|
npm install rollup rollup-plugin-node-resolve rollup-plugin-commonjs rollup-plugin-uglify --save-dev
|
||||||
:marked
|
:marked
|
||||||
Next, create a configuration file to tell Rollup how to process the application.
|
Next, create a configuration file (`rollup-config.js`)
|
||||||
The configuration file in this cookbook is named `rollup.js` and looks like this.
|
in the project root directory to tell Rollup how to process the application.
|
||||||
|
The cookbook configuration file looks like this.
|
||||||
|
|
||||||
+makeExample('cb-aot-compiler/ts/rollup.js', null, 'rollup.js')(format='.')
|
+makeExample('cb-aot-compiler/ts/rollup-config.js', null, 'rollup-config.js')(format='.')
|
||||||
:marked
|
:marked
|
||||||
It tells Rollup that the app entry point is `app/main.js` .
|
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.
|
The `dest` attribute tells Rollup to create a bundle called `build.js` in the `dist` folder.
|
||||||
|
@ -228,7 +251,7 @@ code-example(format='.').
|
||||||
to use the ES `import` and `export` statements that Rollup requires.
|
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.
|
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='.')
|
+makeExample('cb-aot-compiler/ts/rollup-config.js','commonjs','rollup-config.js (CommonJs to ES2015 Plugin)')(format='.')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
*Minification*
|
*Minification*
|
||||||
|
@ -236,7 +259,7 @@ code-example(format='.').
|
||||||
Rollup Tree Shaking reduces code size considerably. Minification makes it smaller still.
|
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.
|
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='.')
|
+makeExample('cb-aot-compiler/ts/rollup-config.js','uglify','rollup-config.js (CommonJs to ES2015 Plugin)')(format='.')
|
||||||
|
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
|
@ -247,7 +270,7 @@ code-example(format='.').
|
||||||
### Run Rollup
|
### Run Rollup
|
||||||
Execute the Rollup process with this command:
|
Execute the Rollup process with this command:
|
||||||
code-example(format='.').
|
code-example(format='.').
|
||||||
node_modules/.bin/rollup -c rollup.js
|
node_modules/.bin/rollup -c rollup-config.js
|
||||||
|
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
|
@ -283,21 +306,178 @@ code-example(format='.').
|
||||||
a#source-code
|
a#source-code
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Source Code
|
## AoT QuickStart Source Code
|
||||||
|
|
||||||
Here is the pertinent AoT source code for this cookbook:
|
Here's the pertinent source code:
|
||||||
+makeTabs(
|
+makeTabs(
|
||||||
`cb-aot-compiler/ts/app/app.component.html,
|
`cb-aot-compiler/ts/app/app.component.html,
|
||||||
cb-aot-compiler/ts/app/app.component.ts,
|
cb-aot-compiler/ts/app/app.component.ts,
|
||||||
cb-aot-compiler/ts/app/main.ts,
|
cb-aot-compiler/ts/app/main.ts,
|
||||||
cb-aot-compiler/ts/index.html,
|
cb-aot-compiler/ts/index.html,
|
||||||
cb-aot-compiler/ts/tsconfig-aot.json,
|
cb-aot-compiler/ts/tsconfig-aot.json,
|
||||||
cb-aot-compiler/ts/rollup.js`,
|
cb-aot-compiler/ts/rollup-config.js`,
|
||||||
null,
|
null,
|
||||||
`app/app.component.html,
|
`app/app.component.html,
|
||||||
app/app.component.ts,
|
app/app.component.ts,
|
||||||
app/main.ts,
|
app/main.ts,
|
||||||
index.html,
|
index.html,
|
||||||
tsconfig-aot.json,
|
tsconfig-aot.json,
|
||||||
rollup.js`
|
rollup-config.js`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
a#toh
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## Tour of Heroes
|
||||||
|
|
||||||
|
The sample above is a trivial variation of the QuickStart app.
|
||||||
|
In this section you apply what you've learned about AoT compilation and Tree Shaking
|
||||||
|
to an app with more substance, the tutorial [_Tour of Heroes_](../tutorial/toh-pt6.html).
|
||||||
|
|
||||||
|
### JiT in development, AoT in production
|
||||||
|
|
||||||
|
Today AoT compilation and Tree Shaking take more time than is practical for development. That will change soon.
|
||||||
|
For now, it's best to JiT compile in development and switch to AoT compilation before deploying to production.
|
||||||
|
|
||||||
|
Fortunately, the source code can be compiled either way without change _if_ you account for a few key differences.
|
||||||
|
|
||||||
|
***Index.html***
|
||||||
|
|
||||||
|
The JiT and AoT apps are setup and launched so differently that they require their own `index.html` files.
|
||||||
|
Here they are for comparison:
|
||||||
|
|
||||||
|
+makeTabs(
|
||||||
|
`toh-6/ts/aot/index.html,
|
||||||
|
toh-6/ts/index.html`,
|
||||||
|
null,
|
||||||
|
`aot/index.html (AoT),
|
||||||
|
index.html (JiT)`
|
||||||
|
)
|
||||||
|
|
||||||
|
:marked
|
||||||
|
They can't be in the same folder.
|
||||||
|
***Put the AoT version in the `/aot` folder***.
|
||||||
|
|
||||||
|
The JiT version relies on `SystemJS` to load individual modules and requires the `reflect-metadata` shim.
|
||||||
|
Both scripts appear in its `index.html`.
|
||||||
|
|
||||||
|
The AoT version loads the entire application in a single script, `aot/dist/build.js`.
|
||||||
|
It does not need `SystemJS` or the `reflect-metadata` shim; those scripts are absent from its `index.html`
|
||||||
|
|
||||||
|
*Component-relative Template URLS*
|
||||||
|
|
||||||
|
The AoT compiler requires that `@Component` URLS for external templates and css files be _component-relative_.
|
||||||
|
That means that the value of `@Component.templateUrl` is a URL value relative to the component class file:
|
||||||
|
`foo.component.html` no matter where `foo.component.ts` sits in the project folder structure.
|
||||||
|
|
||||||
|
While JiT app URLs are more flexible, stick with _component-relative_ URLs for compatibility with AoT compilation.
|
||||||
|
|
||||||
|
JiT-compiled apps, using the SystemJS loader and _component-relative_ URLs *must set the* `@Component.moduleId` *property to* `module.id`.
|
||||||
|
The `module` object is undefined when an AoT-compiled app runs.
|
||||||
|
The app fails unless you assign a global `module` value in the `index.html` like this:
|
||||||
|
+makeExample('toh-6/ts/aot/index.html','moduleId')(format='.')
|
||||||
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
Setting a global `module` is a temporary expedient.
|
||||||
|
:marked
|
||||||
|
*TypeScript configuration*
|
||||||
|
|
||||||
|
JiT-compiled apps transpile to `commonjs` modules.
|
||||||
|
AoT-compiled apps transpile to _ES2015_/_ES6_ modules to facilitate Tree Shaking.
|
||||||
|
AoT requires its own TypeScript configuration settings as well.
|
||||||
|
|
||||||
|
You'll need separate TypeScript configuration files such as these:
|
||||||
|
|
||||||
|
+makeTabs(
|
||||||
|
`toh-6/ts/tsconfig-aot.json,
|
||||||
|
toh-6/ts/tsconfig.json`,
|
||||||
|
null,
|
||||||
|
`tsconfig.json (AoT),
|
||||||
|
tsconfig-aot.json (JiT)`
|
||||||
|
)
|
||||||
|
|
||||||
|
:marked
|
||||||
|
### Tree Shaking
|
||||||
|
|
||||||
|
Rollup does the Tree Shaking as before.
|
||||||
|
|
||||||
|
The Rollup configuration changes slightly to accommodate the `angular-in-memory-web-api` module
|
||||||
|
that the _Tour of Heroes_ app requires for data server simulation.
|
||||||
|
|
||||||
|
The `angular-in-memory-web-api` is a `commonjs` module like the RxJS library.
|
||||||
|
Add `angular-in-memory-web-api` to the _commonjs plugin_ `include` array,
|
||||||
|
next to the `rxjs` file specification.
|
||||||
|
|
||||||
|
+makeExample('toh-6/ts/rollup-config.js',null,'rollup-config.js')(format='.')
|
||||||
|
|
||||||
|
:marked
|
||||||
|
### Running the application
|
||||||
|
|
||||||
|
.alert.is-important
|
||||||
|
:marked
|
||||||
|
The general audience instructions for running the AoT build of the Tour of Heroes app are not ready.
|
||||||
|
|
||||||
|
The following instructions presuppose that you have cloned the
|
||||||
|
<a href="https://github.com/angular/angular.io" target="_blank">angular.io</a>
|
||||||
|
github repository and prepared it for development as explained in the repo's README.md.
|
||||||
|
|
||||||
|
The _Tour of Heroes_ source code is in the `public/docs/_examples/toh-6/ts` folder.
|
||||||
|
:marked
|
||||||
|
Run the JiT-compiled app with `npm start` as for all other JiT examples.
|
||||||
|
|
||||||
|
Compiling with AoT presupposes certain supporting files, most of them discussed above.
|
||||||
|
+makeTabs(
|
||||||
|
`toh-6/ts/aot/index.html,
|
||||||
|
toh-6/ts/aot/bs-config.json,
|
||||||
|
toh-6/ts/copy-dist-files.js,
|
||||||
|
toh-6/ts/rollup-config.js,
|
||||||
|
toh-6/ts/tsconfig-aot.json`,
|
||||||
|
null,
|
||||||
|
`aot/index.html,
|
||||||
|
aot/bs-config.json,
|
||||||
|
copy-dist-files.js,
|
||||||
|
rollup-config.js,
|
||||||
|
tsconfig-aot.json`)
|
||||||
|
:marked
|
||||||
|
Extend the `scripts` section of the `package.json` with these npm scripts:
|
||||||
|
code-example(format='.').
|
||||||
|
"build:aot": "ngc -p tsconfig-aot.json && rollup -c rollup-config.js",
|
||||||
|
"lite:aot": "lite-server -c aot/bs-config.json",
|
||||||
|
:marked
|
||||||
|
Copy the AoT distribution files into the `/aot` folder with the node script:
|
||||||
|
code-example(format='.').
|
||||||
|
node copy-dist-files
|
||||||
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
You won't do that again until there are updates to `zone.js` or the `core-js` shim for old browsers.
|
||||||
|
:marked
|
||||||
|
Now AoT-compile the app and launch it with the `lite` server:
|
||||||
|
code-example(format='.').
|
||||||
|
npm run build:aot && npm run lite:aot
|
||||||
|
|
||||||
|
:marked
|
||||||
|
### Inspect the Bundle
|
||||||
|
|
||||||
|
It's fascinating to see what the generated JavaScript bundle looks like after Rollup.
|
||||||
|
The code is minified, so you won't learn much from inspecting the bundle directly.
|
||||||
|
But the <a href="https://github.com/danvk/source-map-explorer/blob/master/README.md" target="_blank">source-map-explorer</a>
|
||||||
|
tool can be quite revealing.
|
||||||
|
|
||||||
|
Install it:
|
||||||
|
code-example(format='.').
|
||||||
|
npm install source-map-explorer --save-dev
|
||||||
|
:marked
|
||||||
|
Run the following command to generate the map.
|
||||||
|
|
||||||
|
code-example(format='.').
|
||||||
|
node_modules/.bin/source-map-explorer aot/dist/build.js
|
||||||
|
|
||||||
|
:marked
|
||||||
|
The `source-map-explorer` analyzes the source map generated with the bundle and draws a map of all dependencies,
|
||||||
|
showing exactly which application and Angular modules and classes are included in the bundle.
|
||||||
|
|
||||||
|
Here's the map for _Tour of Heroes_.
|
||||||
|
|
||||||
|
a(href="/resources/images/cookbooks/aot-compiler/toh6-bundle.png", target="_blank", title="View larger image")
|
||||||
|
figure.image-display
|
||||||
|
img(src="/resources/images/cookbooks/aot-compiler/toh6-bundle.png" alt="TOH-6-bundle")
|
||||||
|
|
|
@ -7,6 +7,12 @@ block includes
|
||||||
The Angular documentation is a living document with continuous improvements.
|
The Angular documentation is a living document with continuous improvements.
|
||||||
This log calls attention to recent significant changes.
|
This log calls attention to recent significant changes.
|
||||||
|
|
||||||
|
## NEW "Ahead of Time (AoT) Compilation" cookbook (2016-10-11)
|
||||||
|
The NEW [Ahead of Time (AoT) Compilation](../cookbook/aot-compiler.html) cookbook
|
||||||
|
explains what AoT compilation is and why you'd want it.
|
||||||
|
It demonstrates the basics with a QuickStart app
|
||||||
|
followed by the more advanced considerations of compiling and bundling the Tour of Heroes.
|
||||||
|
|
||||||
## Sync with Angular v.2.0.2 (2016-10-6)
|
## Sync with Angular v.2.0.2 (2016-10-6)
|
||||||
Docs and code samples updated and tested with Angular v.2.0.2
|
Docs and code samples updated and tested with Angular v.2.0.2
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 351 KiB |
Loading…
Reference in New Issue