Skip to content

Commit c597344

Browse files
colinskowjoshwiens
authored andcommitted
feature: added AOT compile support (PatrickJS#885) (PatrickJS#1298)
* feature: added AOT compile support (PatrickJS#885) * updated travis.yml with new ci script * removed yarn.lock from .gitignore * (optimize) vendor tree shaking and bundle analysis tool * (fix) support node 5 * upgraded to webpack 2.2.0-rc-2, removed analyzer
1 parent 02716cc commit c597344

File tree

13 files changed

+169
-77
lines changed

13 files changed

+169
-77
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ npm-debug.log
5353
/dist/**
5454
/.awcache
5555
.webpack.json
56+
compiled/
5657

5758
# Doc #
5859
/doc/

.travis.yml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,4 @@ before_script:
2424
- sh -e /etc/init.d/xvfb start
2525
- sleep 3
2626
script:
27-
- npm run lint
28-
- npm test
29-
- npm run build:prod
30-
- npm run server:prod:ci &
31-
- sleep 3
32-
- npm run e2e
27+
- npm run ci

README.md

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ ___
2121
# Angular2 Webpack Starter [![Join Slack](https://img.shields.io/badge/slack-join-brightgreen.svg)](https://angularclass.com/slack-join) [![Join the chat at https://gitter.im/angularclass/angular2-webpack-starter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/angularclass/angular2-webpack-starter?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
2222

2323

24-
> An Angular 2 starter kit featuring [Angular 2](https://angular.io) and [Angular 4](https://github.com/angular/angular/tree/4.0.0-beta.0) ([Router](https://angular.io/docs/js/latest/api/router/), [Forms](https://angular.io/docs/js/latest/api/forms/),
25-
[Http](https://angular.io/docs/js/latest/api/http/),
24+
> An Angular 2 starter kit featuring [Angular 2](https://angular.io) and [Angular 4](https://github.com/angular/angular/tree/4.0.0-beta.0) ([Ahead of Time Compile](https://angular.io/docs/ts/latest/cookbook/aot-compiler.html), [Router](https://angular.io/docs/ts/latest/guide/router.html), [Forms](https://angular.io/docs/ts/latest/guide/forms.html),
25+
[Http](https://angular.io/docs/ts/latest/guide/server-communication.html),
2626
[Services](https://gist.github.com/gdi2290/634101fec1671ee12b3e#_follow_@AngularClass_on_twitter),
27-
[Tests](https://angular.io/docs/js/latest/api/test/), [E2E](https://angular.github.io/protractor/#/faq#what-s-the-difference-between-karma-and-protractor-when-do-i-use-which-)), [Material](https://github.com/angular/material2), [Karma](https://karma-runner.github.io/), [Protractor](https://angular.github.io/protractor/), [Jasmine](https://github.com/jasmine/jasmine), [Istanbul](https://github.com/gotwarlost/istanbul), [TypeScript](http://www.typescriptlang.org/), [@types](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&cad=rja&uact=8&ved=0ahUKEwjgjdrR7u_NAhUQ7GMKHXgpC4EQFggnMAI&url=https%3A%2F%2Fwww.npmjs.com%2F~types&usg=AFQjCNG2PFhwEo88JKo12mrw_4d0w1oNiA&sig2=N69zbO0yN8ET7v4KVCUOKA), [TsLint](http://palantir.github.io/tslint/), [Codelyzer](https://github.com/mgechev/codelyzer), [Hot Module Replacement](https://webpack.github.io/docs/hot-module-replacement-with-webpack.html), and [Webpack 2](http://webpack.github.io/) by [AngularClass](https://angularclass.com).
27+
[Tests](https://angular.io/docs/ts/latest/guide/testing.html), [E2E](https://angular.github.io/protractor/#/faq#what-s-the-difference-between-karma-and-protractor-when-do-i-use-which-)), [Material](https://github.com/angular/material2), [Karma](https://karma-runner.github.io/), [Protractor](https://angular.github.io/protractor/), [Jasmine](https://github.com/jasmine/jasmine), [Istanbul](https://github.com/gotwarlost/istanbul), [TypeScript](http://www.typescriptlang.org/), [@types](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&cad=rja&uact=8&ved=0ahUKEwjgjdrR7u_NAhUQ7GMKHXgpC4EQFggnMAI&url=https%3A%2F%2Fwww.npmjs.com%2F~types&usg=AFQjCNG2PFhwEo88JKo12mrw_4d0w1oNiA&sig2=N69zbO0yN8ET7v4KVCUOKA), [TsLint](http://palantir.github.io/tslint/), [Codelyzer](https://github.com/mgechev/codelyzer), [Hot Module Replacement](https://webpack.github.io/docs/hot-module-replacement-with-webpack.html), and [Webpack 2](http://webpack.github.io/) by [AngularClass](https://angularclass.com).
2828

2929
> If you're looking for Angular 1.x please use [NG6-starter](https://github.com/angularclass/NG6-starter)
3030
> If you're looking to learn about Webpack and ES6 Build Tools check out [ES6-build-tools](https://github.com/AngularClass/ES6-build-tools)
@@ -37,6 +37,8 @@ This seed repo serves as an Angular 2 starter for anyone looking to get up and r
3737
* Ready to go build system using Webpack for working with TypeScript.
3838
* Angular 2 examples that are ready to go when experimenting with Angular 2.
3939
* A great Angular 2 seed repo for anyone who wants to start their project.
40+
* Ahead of Time (AoT) compile for rapid page loads of your production builds.
41+
* Tree shaking to automatically remove unused code from your production bundle.
4042
* Testing Angular 2 code with Jasmine and Karma.
4143
* Coverage with Istanbul and Karma
4244
* End-to-end Angular 2 code using Protractor.
@@ -168,8 +170,10 @@ npm run server:prod
168170
```bash
169171
# development
170172
npm run build:dev
171-
# production
173+
# production (jit)
172174
npm run build:prod
175+
# AoT
176+
npm run build:aot
173177
```
174178

175179
### hot module replacement
@@ -182,7 +186,7 @@ npm run server:dev:hmr
182186
npm run watch
183187
```
184188

185-
### run tests
189+
### run unit tests
186190
```bash
187191
npm run test
188192
```
@@ -194,10 +198,16 @@ npm run watch:test
194198

195199
### run end-to-end tests
196200
```bash
197-
# make sure you have your server running in another terminal
201+
# this will start a test server and launch Protractor
198202
npm run e2e
199203
```
200204

205+
### continuous integration (run unit tests and e2e tests together)
206+
```bash
207+
# this will test both your JIT and AoT builds
208+
npm run ci
209+
```
210+
201211
### run webdriver (for end-to-end)
202212
```bash
203213
npm run webdriver:update
@@ -219,6 +229,16 @@ npm run build:docker
219229
# Configuration
220230
Configuration files live in `config/` we are currently using webpack, karma, and protractor for different stages of your application
221231

232+
# AoT Don'ts
233+
The following are some things that will make AoT compile fail.
234+
235+
- Don’t use require statements for your templates or styles, use styleUrls and templateUrls, the angular2-template-loader plugin will change it to require at build time.
236+
- Don’t use default exports.
237+
- Don’t use form.controls.controlName, use form.get(‘controlName’)
238+
- Don’t use control.errors?.someError, use control.hasError(‘someError’)
239+
- Don’t use functions in your providers, routes or declarations, export a function and then reference that function name
240+
- Inputs, Outputs, View or Content Child(ren), Hostbindings, and any field you use from the template or annotate for Angular should be public
241+
222242
# Contributing
223243
You can include more examples as components but they must introduce a new concept such as `Home` component (separate folders), and Todo (services). I'll accept pretty much everything so feel free to open a Pull-Request
224244

config/helpers.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,19 @@
33
*/
44
var path = require('path');
55

6+
const EVENT = process.env.npm_lifecycle_event || '';
7+
68
// Helper functions
79
var ROOT = path.resolve(__dirname, '..');
810

911
function hasProcessFlag(flag) {
1012
return process.argv.join('').indexOf(flag) > -1;
1113
}
1214

15+
function hasNpmFlag(flag) {
16+
return EVENT.includes(flag);
17+
}
18+
1319
function isWebpackDevServer() {
1420
return process.argv[1] && !! (/webpack-dev-server/.exec(process.argv[1]));
1521
}
@@ -20,5 +26,6 @@ function root(args) {
2026
}
2127

2228
exports.hasProcessFlag = hasProcessFlag;
29+
exports.hasNpmFlag = hasNpmFlag;
2330
exports.isWebpackDevServer = isWebpackDevServer;
2431
exports.root = root;

config/webpack.common.js

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const NormalModuleReplacementPlugin = require('webpack/lib/NormalModuleReplaceme
1414
const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin');
1515
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
1616
const CopyWebpackPlugin = require('copy-webpack-plugin');
17-
const ForkCheckerPlugin = require('awesome-typescript-loader').ForkCheckerPlugin;
17+
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
1818
const HtmlElementsPlugin = require('./html-elements-plugin');
1919
const HtmlWebpackPlugin = require('html-webpack-plugin');
2020
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
@@ -24,6 +24,7 @@ const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
2424
* Webpack Constants
2525
*/
2626
const HMR = helpers.hasProcessFlag('hot');
27+
const AOT = helpers.hasNpmFlag('aot');
2728
const METADATA = {
2829
title: 'Angular2 Webpack Starter by @gdi2290 from @AngularClass',
2930
baseUrl: '/',
@@ -57,8 +58,8 @@ module.exports = function (options) {
5758
entry: {
5859

5960
'polyfills': './src/polyfills.browser.ts',
60-
'vendor': './src/vendor.browser.ts',
61-
'main': './src/main.browser.ts'
61+
'main': AOT ? './src/main.browser.aot.ts' :
62+
'./src/main.browser.ts'
6263

6364
},
6465

@@ -101,9 +102,9 @@ module.exports = function (options) {
101102
test: /\.ts$/,
102103
use: [
103104
'@angularclass/hmr-loader?pretty=' + !isProd + '&prod=' + isProd,
104-
'awesome-typescript-loader',
105+
'awesome-typescript-loader?{configFileName: "tsconfig.webpack.json"}',
105106
'angular2-template-loader',
106-
'angular-router-loader'
107+
'angular-router-loader?loader=system&genDir=compiled/src/app&aot=' + AOT
107108
],
108109
exclude: [/\.(spec|e2e)\.ts$/]
109110
},
@@ -168,7 +169,7 @@ module.exports = function (options) {
168169
*
169170
* See: https://github.com/s-panferov/awesome-typescript-loader#forkchecker-boolean-defaultfalse
170171
*/
171-
new ForkCheckerPlugin(),
172+
new CheckerPlugin(),
172173
/*
173174
* Plugin: CommonsChunkPlugin
174175
* Description: Shares common code between the pages.
@@ -177,6 +178,17 @@ module.exports = function (options) {
177178
* See: https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
178179
* See: https://github.com/webpack/docs/wiki/optimization#multi-page-app
179180
*/
181+
new CommonsChunkPlugin({
182+
name: 'polyfills',
183+
chunks: ['polyfills']
184+
}),
185+
// This enables tree shaking of the vendor modules
186+
new CommonsChunkPlugin({
187+
name: 'vendor',
188+
chunks: ['main'],
189+
minChunks: module => /node_modules\//.test(module.resource)
190+
}),
191+
// Specify the correct order the scripts will be injected in
180192
new CommonsChunkPlugin({
181193
name: ['polyfills', 'vendor'].reverse()
182194
}),

config/webpack.prod.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,16 @@ module.exports = function (env) {
265265
}
266266
}),
267267

268+
/**
269+
* Plugin: BundleAnalyzerPlugin
270+
* Description: Webpack plugin and CLI utility that represents
271+
* bundle content as convenient interactive zoomable treemap
272+
*
273+
* `npm run build:prod -- --env.analyze` to use
274+
*
275+
* See: https://github.com/th0r/webpack-bundle-analyzer
276+
*/
277+
268278
],
269279

270280
/*

package.json

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,32 @@
1111
"homepage": "https://github.com/angularclass/angular2-webpack-starter",
1212
"license": "MIT",
1313
"scripts": {
14-
"build:dev": "webpack --config config/webpack.dev.js --progress --profile",
14+
"build:aot:prod": "npm run clean:dist && npm run clean:aot && npm run ngc && webpack --config config/webpack.prod.js --progress --profile --bail",
15+
"build:aot": "npm run build:aot:prod",
16+
"build:dev": "npm run clean:dist && webpack --config config/webpack.dev.js --progress --profile",
1517
"build:docker": "npm run build:prod && docker build -t angular2-webpack-start:latest .",
16-
"build:prod": "webpack --config config/webpack.prod.js --progress --profile --bail",
18+
"build:prod": "npm run clean:dist && webpack --config config/webpack.prod.js --progress --profile --bail",
1719
"build": "npm run build:dev",
18-
"ci": "npm run lint && npm test && npm run e2e",
20+
"ci:aot": "npm run lint && npm run test && npm run build:aot && npm run e2e",
21+
"ci:jit": "npm run lint && npm run test && npm run build:prod && npm run e2e",
22+
"ci:nobuild": "npm run lint && npm test && npm run e2e",
23+
"ci:testall": "npm run lint && npm run test && npm run build:prod && npm run e2e && npm run build:aot && npm run e2e",
24+
"ci": "npm run ci:testall",
25+
"clean:aot": "npm run rimraf -- compiled",
1926
"clean:dist": "npm run rimraf -- dist",
2027
"clean:install": "npm set progress=false && npm install",
2128
"clean:start": "npm start",
22-
"clean": "npm cache clean && npm run rimraf -- node_modules doc coverage dist",
29+
"clean": "npm cache clean && npm run rimraf -- node_modules doc coverage dist compiled",
2330
"docker": "docker",
2431
"docs": "npm run typedoc -- --options typedoc.json --exclude '**/*.spec.ts' ./src/",
2532
"e2e:live": "npm run e2e -- --elementExplorer",
26-
"e2e": "npm run protractor",
33+
"e2e": "npm-run-all -p -r server:prod:ci e2e:only",
34+
"e2e:only": "npm run protractor",
2735
"github-deploy:dev": "webpack --config config/webpack.github-deploy.js --progress --profile --env.githubDev",
2836
"github-deploy:prod": "webpack --config config/webpack.github-deploy.js --progress --profile --env.githubProd",
2937
"github-deploy": "npm run github-deploy:dev",
3038
"lint": "npm run tslint \"src/**/*.ts\"",
39+
"ngc": "./node_modules/.bin/ngc -p tsconfig.webpack.json",
3140
"postversion": "git push && git push --tags",
3241
"prebuild:dev": "npm run clean:dist",
3342
"prebuild:prod": "npm run clean:dist",
@@ -39,8 +48,8 @@
3948
"rimraf": "rimraf",
4049
"server:dev:hmr": "npm run server:dev -- --inline --hot",
4150
"server:dev": "webpack-dev-server --config config/webpack.dev.js --progress --profile --watch --content-base src/",
42-
"server:prod": "http-server dist --cors",
43-
"server:prod:ci": "http-server dist -p 3000 --cors",
51+
"server:prod": "http-server dist -c-1 --cors",
52+
"server:prod:ci": "http-server dist -p 3000 -c-1 --cors",
4453
"server": "npm run server:dev",
4554
"start:hmr": "npm run server:dev:hmr",
4655
"start": "npm run server:dev",
@@ -60,36 +69,38 @@
6069
"webpack": "webpack"
6170
},
6271
"dependencies": {
63-
"@angular/common": "2.2.1",
64-
"@angular/compiler": "2.2.1",
65-
"@angular/core": "2.2.1",
66-
"@angular/forms": "2.2.1",
67-
"@angular/http": "2.2.1",
68-
"@angular/platform-browser": "2.2.1",
69-
"@angular/platform-browser-dynamic": "2.2.1",
70-
"@angular/platform-server": "2.2.1",
71-
"@angular/router": "3.2.1",
72+
"@angular/common": "~2.4.1",
73+
"@angular/compiler": "~2.4.1",
74+
"@angular/core": "~2.4.1",
75+
"@angular/forms": "~2.4.1",
76+
"@angular/http": "~2.4.1",
77+
"@angular/platform-browser": "~2.4.1",
78+
"@angular/platform-browser-dynamic": "~2.4.1",
79+
"@angular/platform-server": "~2.4.1",
80+
"@angular/router": "~3.4.1",
7281
"@angularclass/conventions-loader": "^1.0.2",
7382
"@angularclass/hmr": "~1.2.2",
7483
"@angularclass/hmr-loader": "~3.0.2",
7584
"assets-webpack-plugin": "^3.4.0",
7685
"core-js": "^2.4.1",
7786
"http-server": "^0.9.0",
7887
"ie-shim": "^0.1.0",
79-
"rxjs": "5.0.0-beta.12",
80-
"zone.js": "~0.6.26"
88+
"reflect-metadata": "^0.1.9",
89+
"rxjs": "~5.0.2",
90+
"zone.js": "~0.7.4"
8191
},
8292
"devDependencies": {
93+
"@angular/compiler-cli": "~2.4.1",
8394
"@types/hammerjs": "^2.0.33",
8495
"@types/jasmine": "^2.2.34",
8596
"@types/node": "^6.0.38",
8697
"@types/selenium-webdriver": "2.53.33",
8798
"@types/source-map": "^0.1.27",
8899
"@types/uglify-js": "^2.0.27",
89-
"@types/webpack": "^1.12.34",
100+
"@types/webpack": "^2.0.0",
90101
"angular-router-loader": "^0.4.0",
91102
"angular2-template-loader": "^0.6.0",
92-
"awesome-typescript-loader": "^2.2.1",
103+
"awesome-typescript-loader": "~3.0.0-beta.17",
93104
"codelyzer": "~1.0.0-beta.4",
94105
"copy-webpack-plugin": "^4.0.0",
95106
"css-loader": "^0.26.0",
@@ -109,6 +120,7 @@
109120
"karma-remap-coverage": "^0.1.1",
110121
"karma-sourcemap-loader": "^0.3.7",
111122
"karma-webpack": "1.8.0",
123+
"npm-run-all": "^3.1.2",
112124
"parse5": "^2.2.2",
113125
"protractor": "^4.0.10",
114126
"raw-loader": "0.5.1",
@@ -123,12 +135,12 @@
123135
"tslint": "~3.15.1",
124136
"tslint-loader": "^2.1.5",
125137
"typedoc": "^0.5.0",
126-
"typescript": "2.1.1",
138+
"typescript": "2.0.10",
127139
"url-loader": "^0.5.7",
128140
"v8-lazy-parse-webpack-plugin": "^0.3.0",
129-
"webpack": "2.1.0-beta.27",
141+
"webpack": "2.2.0-rc.2",
130142
"webpack-dev-middleware": "^1.6.1",
131-
"webpack-dev-server": "2.1.0-beta.11",
143+
"webpack-dev-server": "2.2.0-rc.0",
132144
"webpack-md5-hash": "^0.0.5",
133145
"webpack-merge": "~1.0.1"
134146
},

src/app/+detail/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ export const routes = [
2222
RouterModule.forChild(routes),
2323
]
2424
})
25-
export default class AboutModule {
25+
export class AboutModule {
2626
static routes = routes;
2727
}

src/app/app.routes.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ export const ROUTES: Routes = [
1010
{ path: '', component: HomeComponent },
1111
{ path: 'home', component: HomeComponent },
1212
{ path: 'about', component: AboutComponent },
13-
{
14-
path: 'detail', loadChildren: () => System.import('./+detail')
15-
.then((comp: any) => comp.default),
16-
},
13+
{ path: 'detail', loadChildren: './+detail/index#AboutModule'},
1714
{ path: '**', component: NoContentComponent },
1815
];

src/main.browser.aot.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Angular bootstraping
3+
*/
4+
import { platformBrowser } from '@angular/platform-browser';
5+
import { decorateModuleRef } from './app/environment';
6+
/*
7+
* App Module
8+
* our top level module that holds all of our components
9+
*/
10+
import { AppModuleNgFactory } from '../compiled/src/app/app.module.ngfactory';
11+
12+
/*
13+
* Bootstrap our Angular app with a top level NgModule
14+
*/
15+
export function main(): Promise<any> {
16+
return platformBrowser()
17+
.bootstrapModuleFactory(AppModuleNgFactory)
18+
.then(decorateModuleRef)
19+
.catch(err => console.error(err));
20+
}
21+
22+
export function bootstrapDomReady() {
23+
document.addEventListener('DOMContentLoaded', main);
24+
}
25+
26+
bootstrapDomReady();

0 commit comments

Comments
 (0)