The latest release of Angular2 allows for Ahead of time (AOT) compilation, using this code in your app.bootstrap.ts file:
// The browser platform without a co
I got it working finally, see my repo Angular2 Webpack2 DotNET Starter
There are several tricks necessary. Note that AOT compilation does not support any require()
statements in your Angular 2 components. They will need to be converted to import
statements.
First, you need to have a second tsconfig.json
file, with special options for AOT compilation. I designate this with .aot.json
extension.
tsconfig.aot.json :
{
"compilerOptions": {
"target": "es5",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": false,
"noEmitHelpers": true,
"pretty": true,
"strictNullChecks": false,
"baseUrl": ".",
"sourceMap": true,
"sourceRoot": ".",
"lib": [
"es6",
"dom"
],
"types": [
"lodash",
"hammerjs",
"jasmine",
"node",
"selenium-webdriver",
"source-map",
"uglify-js",
"webpack",
"materialize-css",
"jquery",
"kendo-ui"
],
"typeRoots": [
"./node_modules/@types"
],
"outDir": "./compiled/src"
},
"exclude": [
"./node_modules",
"./**/*.e2e.ts",
"./**/*.spec.ts",
],
"awesomeTypescriptLoaderOptions": {
"useWebpackText": true,
"forkChecker": true,
"useCache": true
},
"compileOnSave": false,
"buildOnSave": false,
"atom": {
"rewriteTsconfig": false
},
"angularCompilerOptions": {
"genDir": "./compiled/aot",
"debug": true
}
}
You'll also need the exact right combination of verions of Angular2. @angular/core@2.0.2
and @angular/common@2.0.2
did NOT work for me, I had to use 2.0.0
for both or ngc
failed to compile the AOT files. Here's what I'm using successfully:
package.json :
"dependencies": {
"@angular/core": "2.0.0",
"@angular/common": "2.0.0",
"@angular/compiler": "2.0.0",
"@angular/compiler-cli": "0.6.2",
"@angular/forms": "^2.0.1",
"@angular/http": "2.0.0",
"@angular/platform-browser": "2.0.0",
"@angular/platform-browser-dynamic": "2.0.0",
"@angular/platform-server": "2.0.0",
"@angular/router": "3.0.0",
"@angular/tsc-wrapped": "0.3.0"
}
In addition, you'll need a couple nifty webpack loaders, while also allowing webpack to look in the ./src
folder as well as the folder your AOT compiled files are output to. (*.component.ngfactory.ts
)
That last part is very important! If you don't tell webpack to include it those folders, it won't work. In this example, the AOT files are output to /aot-compiled
in the root folder.
webpack.common.js
loaders: [
{
test: /\.ts$/,
include: [helpers.paths.appRoot, helpers.root('./compiled/aot')],
exclude: [/\.(spec|e2e)\.ts$/],
loaders: [
'@angularclass/hmr-loader',
'awesome-typescript-loader',
'angular2-template-loader',
'angular2-router-loader?loader=system',
"angular2-load-children-loader" // this loader replaces loadChildren value to work with AOT/JIT
],
},
]
To generate your AOT files, you'll need an NPM script to do it for you
package.json
"scripts": {
"compile:aot": "./node_modules/.bin/ngc -p ./tsconfig.aot.json",
}
You'll also need to make your webpack config read the AOT version of app.bootstrap.ts
- which is different from the JIT version. I differentiate it with .aot.ts
extension so that in production, webpack uses AOT (app.bootstrap.aot.ts
), but in dev mode, it uses JIT with webpack-dev-server
(app.bootstrap.ts
).
Finally, you run npm run compile:aot
FIRST.
Once your AOT files are output to disk, you run your webpack build with either webpack
or webpack-dev-server
.
For a working example, see my repo Angular2 Webpack2 DotNET Starter. It's integrated with .NET Core 1.0, but for those not using .NET, you can still see how Webpack 2 and Angular 2 are configured.
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "es2015",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": ["es2015", "dom"],
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"typeRoots": [
"./node_modules/@types/"
]
},
"angularCompilerOptions": {
"genDir": "aot",
"skipMetadataEmit" : true
}
}
config/webpack-aot.config.js
/**
* webpack2 config file for ng2 AOT compile
* location : config/webpack.aot.js
*/
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var helpers = require('./helpers');
const ngToolsWebpack = require('@ngtools/webpack');
const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
console.log(helpers.root('src', 'app', 'app.module#AppModule'));
module.exports = {
devtool: 'source-map',
entry: {
'polyfills': './src/polyfills.ts',
'app': './src/main.ts'
},
resolve: {
extensions: ['*', '.ts', '.js']
},
output: {
path: helpers.root('dist'),
publicPath: '/',
filename: '[name].[hash].js',
chunkFilename: '[id].[hash].chunk.js'
},
module: {
rules: [
{
test: /\.ts$/,
loader: '@ngtools/webpack'
},
{
test: /\.html$/,
loader: 'html-loader'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
include: helpers.root('public', 'images'),
loader: 'file-loader',
options: {
//name: '/assets/[name].[hash].[ext]' <-file-loaderError
name: 'assets/[name].[ext]'
}
},
{
test: /\.css$/,
exclude: helpers.root('src', 'app'),
loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' })
},
{
test: /\.css$/,
include: helpers.root('src', 'app'),
loader: 'raw-loader'
},
{
test: /\.scss$/,
exclude: /node_modules/,
loaders: ['raw-loader', 'sass-loader']
},
{
test: /\.sass$/,
exclude: /node_modules/,
loaders: ['raw-loader', 'sass-loader']
}
]
},
plugins: [
// If you want to use jquery in ng2 uncomment this
/*
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),*/
new ngToolsWebpack.AotPlugin({
tsConfigPath: helpers.root('tsconfig-aot.json'),
basePath: helpers.root(''),
entryModule: helpers.root('src', 'app', 'app.module#AppModule'),
mainPath: helpers.root('src', 'main.ts')
}),
new webpack.optimize.CommonsChunkPlugin({
name: ['app', 'polyfills']
}),
new webpack.LoaderOptionsPlugin({
minimize: true,
options: {
htmlLoader: {
minimize: false
}
}
}),
new HtmlWebpackPlugin({
template: 'public/index.html'
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
drop_console: true
},
output: {
comments: false
}
}),
new ExtractTextPlugin('[name].[hash].css'),
new webpack.DefinePlugin({
'process.env': {
'ENV': JSON.stringify(ENV)
}
})
]
};
I used this webpack config and I did AOT compile with angular2 lazy loading. You can see example app for AOT / JIT compile with angular2 lazy load for production mode and dev mode in this git.
angular2-webpack2-aot