实现webpack
打包优化,有两个优化点:
- 如何减少打包时间
- 如何减少打包大小
减少打包时间
1.优化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'
2.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, // 线程开启数
})
]
3.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用法
4.代码压缩相关
-
启用
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
}
})
减少打包大小
1.按需加载,首页加载文件越小越好,将每个页面单独打包为一个文件,(同样对于loadsh
类库也可以使用按需加载),原理即是使用的时候再去下载对应的文件,返回一个promise
,当promise
成功后再去执行回调。
2.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
}
}
3.Tree shaking
它会删除项目中未被引用的代码,而如果在webpack 4
中只要开启生产环境就会自动启动这个功能