docs(aot-cookbook): workflow suggestion; show how to run with JIT

This commit is contained in:
Ward Bell 2017-01-14 14:44:47 -08:00
parent 60b4287a38
commit a4015abc9e
6 changed files with 107 additions and 33 deletions

View File

@ -1,6 +1,6 @@
// #docregion // #docregion
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module'; import { AppModule } from './app.module';
console.log('Running JIT compiled');
platformBrowserDynamic().bootstrapModule(AppModule); platformBrowserDynamic().bootstrapModule(AppModule);

View File

@ -1,6 +1,6 @@
// #docregion // #docregion
import { platformBrowser } from '@angular/platform-browser'; import { platformBrowser } from '@angular/platform-browser';
import { AppModuleNgFactory } from '../aot/app/app.module.ngfactory'; import { AppModuleNgFactory } from '../aot/app/app.module.ngfactory';
console.log('Running AOT compiled');
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory); platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);

View File

@ -0,0 +1,23 @@
<!-- #docregion -->
<!DOCTYPE html>
<html>
<head>
<title>Ahead of time compilation (JIT)</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>
<!-- #docregion jit -->
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('app/main-jit').catch(function(err){ console.error(err); });
</script>
<!-- #enddocregion jit -->
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>

View File

@ -13,12 +13,10 @@
<script>window.module = 'aot';</script> <script>window.module = 'aot';</script>
<!-- #enddocregion moduleId --> <!-- #enddocregion moduleId -->
</head> </head>
<!-- #docregion bundle -->
<body> <body>
<my-app>Loading...</my-app> <my-app>Loading...</my-app>
</body> </body>
<!-- #docregion bundle -->
<script src="dist/build.js"></script> <script src="dist/build.js"></script>
<!-- #enddocregion bundle --> <!-- #enddocregion bundle -->
</html> </html>

View File

@ -11,15 +11,15 @@ export default {
sourceMap: false, sourceMap: false,
format: 'iife', format: 'iife',
onwarn: function(warning) { onwarn: function(warning) {
// skip certain warnings // Skip certain warnings
// Should intercept ... but doesn't in some rollup versions // should intercept ... but doesn't in some rollup versions
if ( warning.code === 'THIS_IS_UNDEFINED' ) { return; } if ( warning.code === 'THIS_IS_UNDEFINED' ) { return; }
// Intercepts in some rollup versions // intercepts in some rollup versions
if ( warning.indexOf("The 'this' keyword is equivalent to 'undefined'") > -1 ) { return; } if ( warning.indexOf("The 'this' keyword is equivalent to 'undefined'") > -1 ) { return; }
// console.warn everything else // console.warn everything else
console.warn ? console.warn( warning.message ) : console.log( warning.message ) ; console.warn( warning.message );
}, },
plugins: [ plugins: [
nodeResolve({jsnext: true, module: true}), nodeResolve({jsnext: true, module: true}),

View File

@ -14,6 +14,7 @@ a#toc
* [Tree Shaking](#tree-shaking) * [Tree Shaking](#tree-shaking)
* [Load the bundle](#load) * [Load the bundle](#load)
* [Serve the app](#serve) * [Serve the app](#serve)
* [Workflow and convenience script](#workflow)
* [Source Code](#source-code) * [Source Code](#source-code)
* [Tour of Heroes](#toh) * [Tour of Heroes](#toh)
@ -104,7 +105,7 @@ a#compile
:marked :marked
Install a few new npm dependencies with the following command: Install a few new npm dependencies with the following command:
code-example(format='.'). code-example(language="none" class="code-shell").
npm install @angular/compiler-cli @angular/platform-server --save npm install @angular/compiler-cli @angular/platform-server --save
:marked :marked
You will run the `ngc` compiler provided in the `@angular/compiler-cli` npm package You will run the `ngc` compiler provided in the `@angular/compiler-cli` npm package
@ -150,7 +151,7 @@ code-example(format='.').
### Compiling the application ### Compiling the application
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(language="none" class="code-shell").
node_modules/.bin/ngc -p tsconfig-aot.json node_modules/.bin/ngc -p tsconfig-aot.json
.l-sub-section .l-sub-section
:marked :marked
@ -188,17 +189,21 @@ a#bootstrap
Instead of bootstrapping `AppModule`, you bootstrap the application with the generated module factory, `AppModuleNgFactory`. Instead of bootstrapping `AppModule`, you bootstrap the application with the generated module factory, `AppModuleNgFactory`.
Switch from the `platformBrowserDynamic.bootstrap` used in JIT compilation to Make a copy of `main.ts` and name it `main-jit.ts`.
`platformBrowser().bootstrapModuleFactory` and pass in the `AppModuleNgFactory`. This is the JIT version; set it aside as you may need it [later](#run-jit "Running with JIT").
Here is AOT bootstrap in `main.ts` next to the familiar JIT version: Open `main.ts` and convert it to AOT compilation.
Switch from the `platformBrowserDynamic.bootstrap` used in JIT compilation to
`platformBrowser().bootstrapModuleFactory` and pass in the AOT-generated `AppModuleNgFactory`.
Here is AOT bootstrap in `main.ts` next to the original JIT version:
+makeTabs( +makeTabs(
`cb-aot-compiler/ts/app/main.ts, `cb-aot-compiler/ts/app/main.ts,
cb-aot-compiler/ts/app/main-jit.ts`, cb-aot-compiler/ts/app/main-jit.ts`,
null, null,
`app/main.ts (AOT), `app/main.ts,
app/main.ts (JIT)` app/main-jit.ts`
) )
:marked :marked
@ -250,6 +255,8 @@ code-example(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.
It overrides the default `onwarn` method in order to skip annoying messages about the AOT compiler's use of the `this` keyword.
Then there are plugins. Then there are plugins.
:marked :marked
@ -288,15 +295,12 @@ code-example(format='.').
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-config.js node_modules/.bin/rollup -c rollup-config.js
.l-sub-section .l-sub-section
:marked :marked
Rollup may log many lines with the following warning message: Windows users should surround the `rollup` command in double quotes:
code-example(format='.', language='bash'). code-example(format='.').
The `this` keyword is equivalent to `undefined` at the top level of an ES module, and has been rewritten "node_modules/.bin/rollup" -c rollup-config.js
:marked :marked
You can safely ignore these warnings.
a#load a#load
.l-main-section .l-main-section
:marked :marked
@ -304,7 +308,7 @@ a#load
Loading the generated application bundle does not require a module loader like SystemJS. Loading the generated application bundle does not require a module loader like SystemJS.
Remove the scripts that concern SystemJS. Remove the scripts that concern SystemJS.
Instead, load the bundle file using a single `script` tag: Instead, load the bundle file using a single `script` tag **_after_** the `</body>` tag:
+makeExample('cb-aot-compiler/ts/index.html','bundle','index.html (load bundle)')(format='.') +makeExample('cb-aot-compiler/ts/index.html','bundle','index.html (load bundle)')(format='.')
@ -315,11 +319,11 @@ a#serve
You'll need a web server to host the application. You'll need a web server to host the application.
Use the same _Lite Server_ employed elsewhere in the documentation: Use the same _Lite Server_ employed elsewhere in the documentation:
code-example(format='.'). code-example(language="none" class="code-shell").
npm run lite npm run lite
:marked :marked
The server starts, launches a browser, and the app should appear. The server starts, launches a browser, and the app should appear.
a#source-code a#source-code
.l-main-section .l-main-section
:marked :marked
@ -342,6 +346,56 @@ a#source-code
rollup-config.js` rollup-config.js`
) )
a#workflow
.l-main-section
:marked
## Workflow and convenience script
You'll rebuild the AOT version of the application every time you make a change.
Those _npm_ commands are long and difficult to remember.
Add the following _npm_ convenience script to the `package.json` so you can compile and rollup in one command.
+makeJson('cb-aot-compiler/ts/package.json', { paths: 'scripts.build:aot'}, "package.json (build:aot convenience script)")
:marked
Open a terminal window and try it.
code-example(language="none" class="code-shell").
npm run build:aot
a#run-jit
:marked
### And JIT too!
AOT compilation and rollup together take several seconds.
You may be able to develop iteratively a little faster with SystemJS and JIT.
The same source code can be built both ways. Here's one way to do that.
* Make a copy of `index.html` and call it `index-jit.html`.
* Delete the script at the bottom of `index-jit.html` that loads `bundle.js`
* Restore the SystemJS scripts like this:
+makeExample('cb-aot-compiler/ts/index-jit.html','jit','index-jit.html (SystemJS scripts)')(format='.')
:marked
Notice the slight change to the `system.import` which now specifies `app/main-jit`.
That's the JIT version of the bootstrap file that we preserved [above](#bootstrap)
:marked
Open a _different_ terminal window and enter.
code-example(language="none" class="code-shell").
npm start
:marked
That compiles the app with JIT and launches the server.
The server loads `index.html` which is still the AOT version (confirm in the browser console).
Change the address bar to `index-jit.html` and it loads the JIT version (confirm in the browser console).
Develop as usual.
The server and TypeScript compiler are in "watch mode" so your changes are reflected immediately in the browser.
To see those changes in AOT, switch to the original terminal and re-run `npm run build:aot`.
When it finishes, go back to the browser and back-button to the AOT version in the (default) `index.html`.
Now you can develop JIT and AOT, side-by-side.
a#toh a#toh
.l-main-section .l-main-section
:marked :marked
@ -459,19 +513,18 @@ a#toh
tsconfig-aot.json`) tsconfig-aot.json`)
:marked :marked
Extend the `scripts` section of the `package.json` with these npm scripts: Extend the `scripts` section of the `package.json` with these npm scripts:
code-example(format='.'). +makeJson('cb-aot-compiler/ts/package.json', { paths: 'scripts.build:aot, scripts.lite:aot'}, "package.json (convenience scripts)")
"build:aot": "ngc -p tsconfig-aot.json && rollup -c rollup-config.js",
"lite:aot": "lite-server -c aot/bs-config.json",
:marked :marked
Copy the AOT distribution files into the `/aot` folder with the node script: Copy the AOT distribution files into the `/aot` folder with the node script:
code-example(format='.'). code-example(language="none" class="code-shell").
node copy-dist-files node copy-dist-files
.l-sub-section .l-sub-section
:marked :marked
You won't do that again until there are updates to `zone.js` or the `core-js` shim for old browsers. You won't do that again until there are updates to `zone.js` or the `core-js` shim for old browsers.
:marked :marked
Now AOT-compile the app and launch it with the `lite` server: Now AOT-compile the app and launch it with the `lite` server:
code-example(format='.'). code-example(language="none" class="code-shell").
npm run build:aot && npm run lite:aot npm run build:aot && npm run lite:aot
:marked :marked
@ -483,12 +536,12 @@ code-example(format='.').
tool can be quite revealing. tool can be quite revealing.
Install it: Install it:
code-example(format='.'). code-example(language="none" class="code-shell").
npm install source-map-explorer --save-dev npm install source-map-explorer --save-dev
:marked :marked
Run the following command to generate the map. Run the following command to generate the map.
code-example(format='.'). code-example(language="none" class="code-shell").
node_modules/.bin/source-map-explorer aot/dist/build.js node_modules/.bin/source-map-explorer aot/dist/build.js
:marked :marked