diff --git a/public/docs/_examples/cb-aot-compiler/e2e-spec.ts b/public/docs/_examples/cb-aot-compiler/e2e-spec.ts
new file mode 100644
index 0000000000..1f7c00704c
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/e2e-spec.ts
@@ -0,0 +1,25 @@
+///
+'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();
+ });
+ });
+});
diff --git a/public/docs/_examples/cb-aot-compiler/ts/.gitignore b/public/docs/_examples/cb-aot-compiler/ts/.gitignore
new file mode 100644
index 0000000000..f2e297bbd3
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/.gitignore
@@ -0,0 +1,5 @@
+**/*.ngfactory.ts
+**/*.metadata.json
+dist
+!app/tsconfig.json
+!rollup.js
\ No newline at end of file
diff --git a/public/docs/_examples/cb-aot-compiler/ts/app/app.component.html b/public/docs/_examples/cb-aot-compiler/ts/app/app.component.html
new file mode 100644
index 0000000000..c6a7babb8b
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/app/app.component.html
@@ -0,0 +1,7 @@
+
+
+
My First Angular 2 App
+
+
List of Heroes
+
{{hero}}
+
diff --git a/public/docs/_examples/cb-aot-compiler/ts/app/app.component.ts b/public/docs/_examples/cb-aot-compiler/ts/app/app.component.ts
new file mode 100644
index 0000000000..8352eb83f3
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/app/app.component.ts
@@ -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;
+ }
+
+}
diff --git a/public/docs/_examples/cb-aot-compiler/ts/app/app.module.ts b/public/docs/_examples/cb-aot-compiler/ts/app/app.module.ts
new file mode 100644
index 0000000000..b4fc185c24
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/app/app.module.ts
@@ -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 { }
diff --git a/public/docs/_examples/cb-aot-compiler/ts/app/main-jit.ts b/public/docs/_examples/cb-aot-compiler/ts/app/main-jit.ts
new file mode 100644
index 0000000000..2a7981d0c5
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/app/main-jit.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/cb-aot-compiler/ts/app/main.ts b/public/docs/_examples/cb-aot-compiler/ts/app/main.ts
new file mode 100644
index 0000000000..f5a9e94209
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/app/main.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { platformBrowser } from '@angular/platform-browser';
+
+import { AppModuleNgFactory } from '../aot/app/app.module.ngfactory';
+
+platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);
diff --git a/public/docs/_examples/cb-aot-compiler/ts/example-config.json b/public/docs/_examples/cb-aot-compiler/ts/example-config.json
new file mode 100644
index 0000000000..1ef73390ce
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/example-config.json
@@ -0,0 +1,4 @@
+{
+ "build": "build:aot",
+ "run": "http-server:e2e"
+}
\ No newline at end of file
diff --git a/public/docs/_examples/cb-aot-compiler/ts/index.html b/public/docs/_examples/cb-aot-compiler/ts/index.html
new file mode 100644
index 0000000000..5d3d6b68c4
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/index.html
@@ -0,0 +1,23 @@
+
+
+
+
+ Ahead of time compilation
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
+
+
diff --git a/public/docs/_examples/cb-aot-compiler/ts/rollup.js b/public/docs/_examples/cb-aot-compiler/ts/rollup.js
new file mode 100644
index 0000000000..5b90e5b0ea
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/rollup.js
@@ -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
\ No newline at end of file
diff --git a/public/docs/_examples/cb-aot-compiler/ts/tsconfig-aot.json b/public/docs/_examples/cb-aot-compiler/ts/tsconfig-aot.json
new file mode 100644
index 0000000000..50cd4b53be
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/tsconfig-aot.json
@@ -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
+ }
+}
diff --git a/public/docs/_examples/package.json b/public/docs/_examples/package.json
index ee913df8f7..314a60f8cd 100644
--- a/public/docs/_examples/package.json
+++ b/public/docs/_examples/package.json
@@ -19,7 +19,8 @@
"start:webpack": "webpack-dev-server --inline --progress --port 8080",
"test:webpack": "karma start karma.webpack.conf.js",
"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": [],
"author": "",
@@ -33,12 +34,16 @@
"@angular/http": "2.0.0-rc.7",
"@angular/platform-browser": "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/upgrade": "2.0.0-rc.7",
"angular2-in-memory-web-api": "0.0.19",
"bootstrap": "^3.3.6",
"core-js": "^2.4.1",
"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",
"systemjs": "0.19.27",
"zone.js": "^0.6.21"
@@ -71,11 +76,12 @@
"protractor": "^3.3.0",
"raw-loader": "^0.5.1",
"rimraf": "^2.5.2",
+ "rollup-plugin-commonjs": "^4.1.0",
"style-loader": "^0.13.1",
"ts-loader": "^0.8.2",
"ts-node": "^0.7.3",
"tslint": "^3.15.1",
- "typescript": "^1.8.10",
+ "typescript": "2.0.2",
"typings": "^1.3.2",
"webpack": "^1.13.0",
"webpack-dev-server": "^1.14.1",
diff --git a/public/docs/ts/latest/cookbook/_data.json b/public/docs/ts/latest/cookbook/_data.json
index 6142c4c6f4..9281abe58d 100644
--- a/public/docs/ts/latest/cookbook/_data.json
+++ b/public/docs/ts/latest/cookbook/_data.json
@@ -5,6 +5,11 @@
"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": {
"title": "Angular 1 to 2 Quick Reference",
"navTitle": "Angular 1 to 2 Quick Ref",
diff --git a/public/docs/ts/latest/cookbook/aot-compiler.jade b/public/docs/ts/latest/cookbook/aot-compiler.jade
new file mode 100644
index 0000000000..7cbd69ee0a
--- /dev/null
+++ b/public/docs/ts/latest/cookbook/aot-compiler.jade
@@ -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 QuickStart 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`
+)