webpack3极速模式
<p>[TOC]</p>
<p>随着项目发展,项目目录会越来越大,项目依赖包会越来越多,会直接影响着项目构建速度,导致项目构建效率极低,比如下面栗子:</p>
<h3>问题出在哪里</h3>
<p>目前有很多工具提供了可视化分析,比如<a href="https://www.npmjs.com/package/webpack-bundle-analyzer" title="webpack-bundle-analyzer">webpack-bundle-analyzer</a>,接下已Webpack-bundle-analyzer为例,它提供了一个下图所示的图表,展示了引入的所有模块的大小、路径等信息,可以针对性的做出优化</p>
<h3>优化方案</h3>
<h4>减小文件搜索范围</h4>
<p>在使用实际项目开发中,为了提升开发效率,会使用第三方组件库;即便自己写的代码,模块间相互引用,为了方便也会使用相对路径,或者别名(<code>alias</code>);这中间如果能使得<code>Webpack</code> 更快寻找到目标,将对打包速度产生很是积极的影响。于此,我们需要做的即:减小文件搜索范围,从而提升速度;实现这一点,具体做法如下:</p>
<h5>配置 resolve.modules</h5>
<p>Webpack的<code>resolve.modules</code>配置模块库(即 <code>node_modules</code>)所在的位置,在 js 里出现 <code>import 'vue'</code> 这样不是相对、也不是绝对路径的写法时,会去 node_modules 目录下找。但是默认的配置,会采用向上递归搜索的方式去寻找,但通常项目目录里只有一个 node_modules,且是在项目根目录,为了减少搜索范围,可以直接写明<code>node_modules</code> 的全路径;同样,对于别名(<code>alias</code>)的配置,亦当如此:</p>
<pre><code>webpack.base.conf.js
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
vue$: 'vue/dist/vue.esm.js',
'@': resolve('src'),
'@assets': resolve('src/assets'),
'@components': resolve('src/components'),
'@config': resolve('src/config'),
'@define': resolve('src/define'),
'@events': resolve('src/events'),
'@pages': resolve('src/pages'),
'@router': resolve('src/router'),
'@store': resolve('src/store'),
'@util': resolve('src/util'),
'@view': resolve('src/view')
}
}</code></pre>
<p>需要额外补充一点的是 自己写的模块组件引用路径 需要改为 <code>import '@***/**.css|js|vue'</code></p>
<h4>增强代码代码压缩工具</h4>
<p><code>Webpack</code>认提供的<code>UglifyJS</code>插件,由于采用单线程压缩,速度颇慢 ;推荐采用<code>webpack-parallel-uglify-plugin</code> 插件, 可以并行运行 UglifyJS 插件,更加充分而合理的使用 CPU 资源,这可以大大减少的构建时间,具体配置如下:</p>
<pre><code>webpack.prod.conf.js
var ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
plugins:[
- new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap
}),
+ new ParallelUglifyPlugin({
cacheDir: '.cache/',
sourceMap: config.build.productionSourceMap,
uglifyJS: {
output: {
comments: false
},
compress: {
warnings: false
}
}
})
]</code></pre>
<h4>用happypack 开启多线程构建</h4>
<p><code>Happypack</code> 的处理思路是:将原有的<code>webpack</code> 对<code>loader</code> 的执行过程,从单一进程的形式扩展多进程模式,从而加速代码构建;原本的流程保持不变,这样可以在不修改原有配置的基础上,来完成对编译过程的优化,具体配置如下:</p>
<pre><code>webpack.base.conf.js
var HappyPack = require('happypack');
const os = require('os');
var happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
plugins: [
new HappyPack({
id: 'happybabel',
loaders: ['babel-loader?cacheDirectory=true'],
threadPool: happyThreadPool,
cache: true,
verbose: true
}),
]
rules: [
// ...
{
test: /\.js$/,
loader: 'happypack/loader?id=happybabel',
include: [
resolve('src'),
resolve('test'),
resolve('node_modules/webpack-dev-server/client')
],
exclude: /node_modules/
}
// ...
]
</code></pre>
<h4>合理配置 babel-loader</h4>
<p>在babel-loader官方有这么一句话 <a href="https://github.com/babel/babel-loader" title="babel-loader is slow!">babel-loader is slow!</a>
在配置babel-loader时需要考虑到这一点
比如,使用 /.js$/来匹配文件的话,可能会将node_modules中的文件一起处理,我们需要使用exclude、include等尽可能准确的来指定需要转换的内容。
我们还可以开启babel的缓存配置(cacheDirectory)来提升一倍以上的效率,配置如下:</p>
<pre><code>webpack.base.conf.js
rules: [
// ...
{
test: /\.js$/,
loader: 'babel-loader?cacheDirectory=true',
include: [
resolve('src'),
resolve('test'),
resolve('node_modules/webpack-dev-server/client')
],
exclude: /node_modules/
},
// ...
]</code></pre>
<h4>Hard cache the source of modules in webpack(硬核)</h4>
<p>HardSourceWebpackPlugin是webpack的插件,为模块提供中间缓存步骤。为了查看结果,您需要使用此插件运行webpack两次:第一次构建将花费正常的时间。第二次构建将显着加快(大概提升90%的构建速度)
具体配置如下:</p>
<pre><code>webpack.base.conf.js
var HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
plugins: [
new HardSourceWebpackPlugin({
// Either an absolute path or relative to webpack's options.context.
cacheDirectory: 'node_modules/.cache/hard-source/[confighash]',
// Either a string of object hash function given a webpack config.
configHash: function(webpackConfig) {
// node-object-hash on npm can be used to build this.
return require('node-object-hash')({ sort: false }).hash(
webpackConfig
);
},
// Either false, a string, an object, or a project hashing function.
environmentHash: {
root: process.cwd(),
directories: ['src'],
files: ['package-lock.json', 'yarn.lock']
},
// An object.
info: {
// 'none' or 'test'.
mode: 'none',
// 'debug', 'log', 'info', 'warn', or 'error'.
level: 'debug'
},
// Clean up large, old caches automatically.
cachePrune: {
// Caches younger than `maxAge` are not considered for deletion. They must
// be at least this (default: 2 days) old in milliseconds.
maxAge: 2 * 24 * 60 * 60 * 1000,
// All caches together must be larger than `sizeThreshold` before any
// caches will be deleted. Together they must be at least this
// (default: 50 MB) big in bytes.
sizeThreshold: 50 * 1024 * 1024
}
})
]</code></pre>
<h3>应用场景说明</h3>
<p>优化文案目前使用移动端脚手架且webpack3环境</p>
<h3>安装依赖包</h3>
<pre><code>
"happypack": "^5.0.1",
"hard-source-webpack-plugin": "^0.13.1",
"node-object-hash": "^1.4.1",
"webpack-parallel-uglify-plugin": "^1.1.0"
```欢迎使用ShowDoc!</code></pre>