查看项目分析图
webpack-bundle-analyzer
2.多进程
HappyPack
注:由于HappyPack作者对js的兴趣逐步丢失,所以之后维护将变少,webpack4及之后推荐使用thread-loader
使用HappyPack
优化打包速度,比如我们有多个模块,交给HappyPack,在webpack compiler的run方法之后,进程就会到达HappyPack
,HappyPack
会做一些初始化,初始化之后会创建一个线程池,线程池会将构建任务里面的模块进行分配,那么一个happyPack的一个线程池会包括多个线程,这时候线程池的这些线程会各自去处理其中的模块以及它的依赖,处理完成之后会有一个通信的过程,会将处理好的资源传输给HappyPack
的一个主进程,完成整个的一个构建过程。
module.exports = override(
addWebpackModuleRule({
test: /\.jsx$/, //
use: [
// 'babel-loader'
'happypack/loader',
]
}),
alter_config()
)
const alter_config = () => (config) => {
config.plugins.push(
/* 多线程编译 */
new HappyPack({
loaders: ['babel-loader']
}),
)
return config
}
原理:与HappyPack类似,每次webpack解析一个模块,thread-loader会将它及它的依赖分配给worker进程中
module.exports = override(
addWebpackModuleRule({
test: /.jsx$/, // 对所有js后缀的文件进行编译
include: resolve('src'), // 表示在src目录下的.js文件都要进行一下使用的loader
use: [
'babel-loader',
{
loader: 'thread-loader',
options: {
workers: 3,
}
}
]
})
)
hard-source-webpack-plugin
抛弃 DLL,选择hard-source-webpack-plugin
dll的概念: 其实是做缓存
所谓动态链接,就是把一些经常会共享的代码制作成 DLL 档,当可执行文件调用到 DLL 档内的函数时,Windows 操作系统才会把 DLL 档加载存储器内,DLL 档本身的结构就是可执行档,当程序有需求时函数才进行链接。透过动态链接方式,存储器浪费的情形将可大幅降低。
将dll和缓存进行对比可以发现:
缓存 DLL 把常用的文件存储到内存或硬盘中 把公共代码打包为dll文件放到硬盘中 再次打包时,直接取读取缓存 再次打包时,读取dll文件,不重新打包 加载时间减少 打包时间减少
2.并行压缩,移除console.log
terser-webpack-plugin
但是因为是webpack4,所以在运用 terser-webpack-plugin 的时候一定要注意版本号,刚开始就是用的5.0.1,要用
"terser-webpack-plugin": "^4.2.3",
版本,否则会报一个 ‘javascript’ 的错误
config.optimization = {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: 4, // 开启并行压缩
terserOptions: {
ecma: undefined,
warnings: false,
parse: {},
compress: {
drop_console: true,
drop_debugger: false,
pure_funcs: ['console.log'], // 移除console
}
}
})
]
}
3.图片压缩
image-webpack-loader
在这里
url-loader
和image-webpack-loader
不能一起使用,否则会导致图片出不来使用
file-loader
搭配,一定要先写file-loader
才能使用image-webpack-loader
通过yarn安装
image-webpack-loader
会导致Error: Cannot find module ‘gifsicle’,使用cnpm安装即可addWebpackModuleRule({ test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, use: [ { loader: 'file-loader', options: { name: '[name]_[hash:8].[ext]', }, }, { loader: 'image-webpack-loader', options: { mozjpeg: { progressive: true, quality: 50 }, optipng: { enabled: false, }, pngquant: { quality: [0.5, 0.65], speed: 4 }, gifsicle: { interlaced: false, }, webp: { quality: 100 } } } ] })
4.去掉无用的css
使用插件purgecss-webpack-plugin
,直接使用配置很简单文档
如果使用css modules
,需要配置白名单whitelistPatterns
,
如果开启css modules
,配合babel-plugin-react-css-modules
一起使用,需要特别注意css的引入方式是import styles from "./index.module.css";
,而不能省略变量styles
。
如果import "./index.module.css";
这样的话,模块话的css
会被忽略。
new MiniCssExtractPlugin({
filename: "css/[name].[contenthash:8].css",
chunkFilename: "css/[name].[contenthash:8].css"
}),
// 放在MiniCssExtractPlugin之后
new PurgecssWebpackPlugin({
// collectWhitelistPatternsChildren: () => {
// return [/^purify-/];
// },
// whitelist: () => {
// return [/\.module\.(css|scss|sass)$/];
// },
whitelistPatterns: () => {
return [/^purify-/];
},
paths: () => glob.sync([`${paths.appSrc}/**/*`], { nodir: true })
})
5.代码分割
webpack4
废弃了CommonsChunkPlugin
插件,使用optimization.splitChunks
和optimization.runtimeChunk
来代替,原因可以参考《webpack4:连奏中的进化》一文。关于runtimeChunk
参数,有的文章说是提取出入口chunk中的runtime部分,形成一个单独的文件,由于这部分不常变化,可以利用缓存。google开发者社区的博文是这样描述的
const code_slicing = () => (config) => {
config.devtool = false
config.optimization = {
minimizer: [
new TerserPlugin({
parallel: 4, // 开启并行压缩
cache: true,
terserOptions: {
ecma: undefined,
warnings: false,
parse: {},
compress: {
drop_console: true,
drop_debugger: false,
pure_funcs: ['console.log'], // 移除console
}
}
})
],
splitChunks: {
cacheGroups: {
earth: {
chunks: 'all',
priority: 1,
test: /[\\/]node_modules[\\/]xt-earth[\\/]/,
name: 'Earth',
minSize: 0,
minChunks: 1
},
editor: {
chunks: 'all',
priority: 1,
test: /[\\/]node_modules[\\/]monaco-editor[\\/]/,
name: 'Editor',
minSize: 0,
minChunks: 1
},
echarts: {
chunks: 'all',
priority: 1,
test: /(echarts|echarts-for-react|echarts-gl)/,
name: 'Echarts',
minSize: 0,
minChunks: 1
},
babel: {
chunks: 'all',
priority: 1,
test: /[\\/]node_modules[\\/]@babel[\\/]/,
name: 'Babel',
minSize: 0,
minChunks: 1
}
}
}
}
return config
}
6.代码压缩
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'), // 匹配文件名
threshold: 10240, // 对10K以上的数据进行压缩
minRatio: 0.8,
deleteOriginalAssets: false // 是否删除源文件
})
需要在nginx配置