I build an Angular 2 application and bundle it with webpack. At the moment, my application is still small but the webpack task already takes around 10 seconds. Is it possible to optimize my webpack config or the TypeSript compilation options to improve the compilation and packaging duration ?
This is the webpack config I use :
var webpack = require('webpack');
var LiveReloadPlugin = require('webpack-livereload-plugin');
module.exports = {
entry: __dirname + '/assets/app/app.ts',
output: {
filename: 'myApp.bundle.js',
path: __dirname + '/build/'
},
// Turn on sourcemaps
devtool: 'source-map',
resolve: {
extensions: ['.ts', '.js']
},
plugins: [
new LiveReloadPlugin({
appendScriptTag: true
}),
// Fixes angular 2 warning
new webpack.ContextReplacementPlugin(
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
__dirname
)
],
module: {
rules: [{
enforce: 'pre',
test: /\.js$/,
loader: "source-map-loader"
},
{
enforce: 'pre',
test: /\.tsx?$/,
use: "ts-loader"
}
]
}
}
And the tsconfig :
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"pretty": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"noUnusedLocals": false,
"removeComments": true,
"skipLibCheck": true,
"strictNullChecks": false,
"baseUrl": "./src",
"typeRoots": ["node_modules/@types"],
"types": [
"core-js",
"systemjs"
],
"outDir": "./build"
},
"exclude": [
"node_modules"
]
}
UPDATE (see my answer for the fixed webpack.config)
I give a try to the DLL webpack plugin suggested by @jpwiddy by compiling angular in a separate build, in order to have to rebuild only the application code during developments and gain considerable time of compilation.
However, after an inspection of the output JS, the file size is quite the same and there is still angular code inside.
Here is the new webpack config file for angular sources :
var webpack = require('webpack');
module.exports = {
entry: {
angular:[
'@angular/platform-browser',
'@angular/platform-browser-dynamic',
'@angular/core',
'@angular/common',
'@angular/compiler',
'@angular/http',
'@angular/router',
'@angular/forms'
]
},
output: {
filename: 'ng2.dll.js',
path: __dirname + '/build/',
library: 'ng2'
},
plugins: [
// Fixes angular 2 warning
new webpack.ContextReplacementPlugin(
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
__dirname
),
new webpack.DllPlugin({
name: 'ng2',
path: __dirname + '/build/ng2.json'
})
]
}
And the updated webpack config for application :
var webpack = require('webpack');
var LiveReloadPlugin = require('webpack-livereload-plugin');
module.exports = {
entry: __dirname + '/assets/app/app.ts',
output: {
filename: 'myApp.bundle.js',
path: __dirname + '/build/'
},
// Turn on sourcemaps
devtool: 'source-map',
resolve: {
extensions: ['.ts', '.js']
},
plugins: [
new LiveReloadPlugin({
appendScriptTag: true
}),
// Fixes angular 2 warning
new webpack.ContextReplacementPlugin(
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
__dirname
),
new webpack.DllReferencePlugin({
context: __dirname + '/build/',
manifest: require(__dirname + '/build/ng2.json')
})
],
module: {
rules: [{
enforce: 'pre',
test: /\.js$/,
loader: "source-map-loader"
},
{
enforce: 'pre',
test: /\.tsx?$/,
use: "ts-loader"
}
]
}
}
Here is one of the angular code I found in my application JS output :
_TsEmitterVisitor.prototype.visitBuiltintType = function (type, ctx) {
var typeStr;
switch (type.name) {
case __WEBPACK_IMPORTED_MODULE_2__output_ast__["R" /* BuiltinTypeName */].Bool:
typeStr = 'boolean';
break;
case __WEBPACK_IMPORTED_MODULE_2__output_ast__["R" /* BuiltinTypeName */].Dynamic:
typeStr = 'any';
break;
case __WEBPACK_IMPORTED_MODULE_2__output_ast__["R" /* BuiltinTypeName */].Function:
typeStr = 'Function';
break;
case __WEBPACK_IMPORTED_MODULE_2__output_ast__["R" /* BuiltinTypeName */].Number:
typeStr = 'number';
break;
case __WEBPACK_IMPORTED_MODULE_2__output_ast__["R" /* BuiltinTypeName */].Int:
typeStr = 'number';
break;
case __WEBPACK_IMPORTED_MODULE_2__output_ast__["R" /* BuiltinTypeName */].String:
typeStr = 'string';
break;
default:
throw new Error("Unsupported builtin type " + type.name);
}
ctx.print(typeStr);
return null;
};
Did I missed something in the new config to prevent webpack including angular sources in the output ?
Thank you
One great way I've personally done that has sped up the Webpack build process is implementing DLLs within your build.
Webpack works by analyzing your code for require
s and import
s, and then builds a table from these statements of all of your module dependencies and links to where those files can be found.
The DLL plugin improves on this, as when you register your dependencies with a DLL, every time those dependencies change (should be very infrequent), you build a DLL (made up of a javascript bundle and a JSON manifest file) and wraps all of those dependencies in a single package. That package is then referenced when pulling in those dependencies into the app.
A quick example:
entry: {
angular:[
'@angular/platform-browser',
'@angular/platform-browser-dynamic',
'@angular/core',
'@angular/common',
'@angular/compiler',
'@angular/http',
'@angular/router',
'@angular/forms'
],
bs: [
'bootstrap',
'ng-bootstrap'
]
},
output: {
filename: '[name].dll.js',
path: outputPath,
library: '[name]',
},
plugins: [
new webpack.DllPlugin({
name: '[name]',
path: join(outputPath, '[name].json')
})
]
... and then referenced as so -
{
plugins: [
new webpack.DllReferencePlugin({
context: process.cwd(),
manifest: require(join(outputPath, 'angular.json'))
}),
new webpack.DllReferencePlugin({
context: process.cwd(),
manifest: require(join(outputPath, 'bs.json'))
}),
]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With