webpack打包优化
实现webpack
打包优化,有两个优化点:
- 如何减少打包时间
- 如何减少打包大小
减少打包时间
-
优化
Loader
对于
Loader
来说,首先优化的当是babel
了,babel
会将代码转成字符串并生成AST
,然后继续转化成新的代码,转换的代码越多,效率就越低。首先可以优化
Loader
的搜索范围module.exports = { module: { rules: [ test: /\.js$/, // 对js文件使用babel loader: 'babel-loader', include: [resolve('src')],// 只在src文件夹下查找 // 不去查找的文件夹路径,node_modules下的代码是编译过得,没必要再去处理一遍 exclude: /node_modules/ ] } }
另外可以将
babel
编译过文件缓存起来,以此加快打包时间,主要在于设置cacheDirectory
loader: 'babel-loader?cacheDirectory=true'
-
HappyPack
因为受限于Node的单线程运行,所以
webpack
的打包也是单线程的,使用HappyPack
可以将Loader
的同步执行转为并行,从而执行Loader
时的编译等待时间。module: { loaders: [ test: /\.js$/, include: [resolve('src')], exclude: /node_modules/, loader: 'happypack/loader?id=happybabel' //id对应插件下的配置的id ] }, plugins: [ new HappyPack({ id: 'happybabel', loaders: ['babel-loader?cacheDirectory'], threads: 4, // 线程开启数 }) ]
-
DllPlugin
该插件可以将特定的类库提前打包然后引入,这种方式可以极大的减少类库的打包次数,只有当类库有更新版本时才会重新打包,并且也实现了将公共代码抽离成单独文件的优化方案。
// webpack.dll.conf.js const path = require('path') const webpack = require('webpack') module.exports = { entry: { vendor: ['react'] // 需要统一打包的类库 }, output: { path: path.join(__dirname, 'dist'), filename: '[name].dll.js', library: '[name]-[hash]' }, plugins: [ new webpack.DllPlugin({ name: '[name]-[hash]', //name必须要和output.library一致 context: __dirname, //注意与DllReferencePlugin的context匹配一致 path: path.join(__dirname, 'dist', '[name]-manifest.json') }) ] }
然后在
package.json
文件中增加一个脚本'dll': 'webpack --config webpack.dll.js --mode=development' //运行后会打包出react.dll.js和manifest.json两个依赖文件
最后使用
DllReferencePlugin
将刚生成的依赖文件引入项目中// webpack.conf.js module.exports = { //...其他配置 plugins: [ new webpack.DllReferencePlugin({ context: __dirname, manifest: require('./dist/vendor-manifest.json') //此即打包出来的json文件 }) ] }
更多有关
webpack
配置DllPlugin
请参考如何使用 Webpack 的 Dllplugin和webpack中DllPlugin用法 -
代码压缩相关
-
启用
gzip
压缩 -
webpack3
中,可以使用UglifyJS
压缩代码,但是它是单线程的,因此可以使用webpack-parallel-uglify-plugin
来运行UglifyJS
,但在webpack4
中只要启动了mode
为production
就默认开启了该配置 -
压缩
html和css
代码,通过配置删除console.log
和debugger
等,防止可能造成的内存泄漏new UglifyJsPlugin({ UglifyOptions: { compress: { warnings: false, drop_console: true, pure_funcs: ['console.log'] } }, sourceMap: config.build.productionSourceMap, parallel: true }) //或使用以下配置 new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false, drop_debugger: true, drop_console: true } })
-
减少打包大小
-
按需加载,首页加载文件越小越好,将每个页面单独打包为一个文件,(同样对于
loadsh
类库也可以使用按需加载),原理即是使用的时候再去下载对应的文件,返回一个promise
,当promise
成功后再去执行回调。 -
Scope Hoisting
它会分析出模块之前的关系,尽可能的把打包出来的模块合并到一个函数中去
// 如在index.js问价中引用了test.js文件 export const a = 1 // test.js import {a} from './test.js' // index.js // 以上打包出来的文件会有两个函数,类似如下 [ function(module, exports, require) {} // **0** function(module, exports, require) {} // **1** ]
如果使用
scope hoisting
的话会尽量打包成一个函数,在webpack 4
中只需开启concatenateModules
即可module.exports = { optimize: { concatenateModules: true } }
-
Tree shaking
它会删除项目中未被引用的代码,而如果在
webpack 4
中只要开启生产环境就会自动启动这个功能