使用 webpack 优化 Angular 2 应用程序构建持续时间
Optimize Angular 2 application build duration with webpack
我构建了一个 Angular 2 应用程序并将其与 webpack 捆绑在一起。
目前,我的应用程序仍然很小,但 webpack 任务已经花费了大约 10 秒。
是否可以优化我的 webpack 配置或 TypeSript 编译选项以缩短编译和打包时间?
这是我使用的 webpack 配置:
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"
}
]
}
}
和 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"
]
}
更新 (请参阅我的固定回答 webpack.config)
我尝试通过在单独的构建中编译 angular 来尝试@jpwiddy 建议的 DLL webpack 插件,以便在开发过程中只重建应用程序代码并获得大量编译时间。
但是查看输出的JS,文件大小还是一样的,里面还有angular代码
这是 angular 来源的新 webpack 配置文件:
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'
})
]
}
以及更新的应用程序 webpack 配置:
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"
}
]
}
}
这是我在应用程序 JS 输出中找到的 angular 代码之一:
_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;
};
我是否遗漏了新配置中的某些内容以防止 webpack 在输出中包含 angular 源?
谢谢
我个人做过的一个加快 Webpack 构建过程的好方法是在你的构建中实现 DLL。
Webpack 通过分析 require
s 和 import
s 的代码来工作,然后根据所有模块依赖项的这些语句构建一个 table 并链接到这些文件的位置可以找到。
DLL 插件对此进行了改进,因为当您使用 DLL 注册依赖项时,每次这些依赖项发生变化 (应该很少见)时,您都会构建一个 DLL(由 javascript 包和JSON 清单文件)并将所有这些依赖项包装在一个包中。然后在将这些依赖项拉入应用程序时引用该包。
一个简单的例子:
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')
})
]
... 然后这样引用 -
{
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'))
}),
]
}
我设法用全新的模块 webpack-dll-bundles-plugin 修复了我的配置(在后台使用 DllPlugin 和 DllReferencePlugin)做我正在寻找的事情:将 Angular 2 的构建隔离在他自己的包中,并避免每次我想重建我的应用程序代码时重建我的整个包(例如使用观察者)。
我的重建时间从 10 秒减少到 1 秒。
这是我的新 webpack 配置:
var webpack = require('webpack');
var LiveReloadPlugin = require('webpack-livereload-plugin');
const DllBundlesPlugin = require('webpack-dll-bundles-plugin').DllBundlesPlugin;
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 DllBundlesPlugin({
bundles: {
vendor: [
'@angular/platform-browser',
'@angular/platform-browser-dynamic',
'@angular/core',
'@angular/common',
'@angular/forms',
'@angular/http',
'@angular/router',
'rxjs',
]
},
dllDir: __dirname + '/build/',
webpackConfig: {}
})
],
module: {
rules: [{
enforce: 'pre',
test: /\.js$/,
loader: "source-map-loader"
},
{
enforce: 'pre',
test: /\.tsx?$/,
use: "ts-loader"
}
]
}
}
我构建了一个 Angular 2 应用程序并将其与 webpack 捆绑在一起。 目前,我的应用程序仍然很小,但 webpack 任务已经花费了大约 10 秒。 是否可以优化我的 webpack 配置或 TypeSript 编译选项以缩短编译和打包时间?
这是我使用的 webpack 配置:
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"
}
]
}
}
和 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"
]
}
更新 (请参阅我的固定回答 webpack.config)
我尝试通过在单独的构建中编译 angular 来尝试@jpwiddy 建议的 DLL webpack 插件,以便在开发过程中只重建应用程序代码并获得大量编译时间。
但是查看输出的JS,文件大小还是一样的,里面还有angular代码
这是 angular 来源的新 webpack 配置文件:
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'
})
]
}
以及更新的应用程序 webpack 配置:
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"
}
]
}
}
这是我在应用程序 JS 输出中找到的 angular 代码之一:
_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;
};
我是否遗漏了新配置中的某些内容以防止 webpack 在输出中包含 angular 源?
谢谢
我个人做过的一个加快 Webpack 构建过程的好方法是在你的构建中实现 DLL。
Webpack 通过分析 require
s 和 import
s 的代码来工作,然后根据所有模块依赖项的这些语句构建一个 table 并链接到这些文件的位置可以找到。
DLL 插件对此进行了改进,因为当您使用 DLL 注册依赖项时,每次这些依赖项发生变化 (应该很少见)时,您都会构建一个 DLL(由 javascript 包和JSON 清单文件)并将所有这些依赖项包装在一个包中。然后在将这些依赖项拉入应用程序时引用该包。
一个简单的例子:
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')
})
]
... 然后这样引用 -
{
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'))
}),
]
}
我设法用全新的模块 webpack-dll-bundles-plugin 修复了我的配置(在后台使用 DllPlugin 和 DllReferencePlugin)做我正在寻找的事情:将 Angular 2 的构建隔离在他自己的包中,并避免每次我想重建我的应用程序代码时重建我的整个包(例如使用观察者)。
我的重建时间从 10 秒减少到 1 秒。
这是我的新 webpack 配置:
var webpack = require('webpack');
var LiveReloadPlugin = require('webpack-livereload-plugin');
const DllBundlesPlugin = require('webpack-dll-bundles-plugin').DllBundlesPlugin;
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 DllBundlesPlugin({
bundles: {
vendor: [
'@angular/platform-browser',
'@angular/platform-browser-dynamic',
'@angular/core',
'@angular/common',
'@angular/forms',
'@angular/http',
'@angular/router',
'rxjs',
]
},
dllDir: __dirname + '/build/',
webpackConfig: {}
})
],
module: {
rules: [{
enforce: 'pre',
test: /\.js$/,
loader: "source-map-loader"
},
{
enforce: 'pre',
test: /\.tsx?$/,
use: "ts-loader"
}
]
}
}