- 使用 webpack 内置 stats
webpack --config webpack.config.js --json > stats.json
特点:输出构建的一些统计信息
缺点:颗粒度较大,无法发现具体问题
- 使用 speed-measure-webpack-plugin
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const smp = new SpeedMeasurePlugin();
const webpackConfig = smp.wrap({
···
plugins: [
new MyPlugin(),
new MyOtherPlugin()
]
···
});
1、分析记录整个打包过程总耗时
2、分析记录每个插件和 loader 的耗时情况
- 使用 webpack-bundle-analyzer
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
···
plugins: [
new BundleAnalyzerPlugin()
]
···
};
构建完成后会自动显示文件大小
1、分析依赖的第三方模块体积大小
2、分析业务里的组件体积大小
- 使用 jarvis
const Jarvis = require('webpack-jarvis');
module.exports = {
···
plugins: [
new Jarvis({
port: 1337 // optional: set a port
})
]
···
};
2、多进程并行解析资源模块
- thread-loader
原理:每次 webpack 解析一个模块,thread-loader 会将它及它的依赖分配给 worker 进程。
module.exports = {
···
module: {
rules: [{
test: /\.js$/,
use: [ 'thread-loader', 'babel-loader' ]
}]
}
···
};
- HappyPack
原理:每次 webpack 解析一个模块,HappyPack 会将它及它的依赖分配到 worker 进程。
const HappyPack = require('happypack');
module.exports = {
···
plugins: [
new HappyPack({
id: 'jsx',
threads: 4,
loaders: [ 'babel-loader' ]
}),
new HappyPack({
id: 'styles',
threads: 2,
loaders: [ 'style-loader', 'css-loader', 'less-loader' ]
})
]
···
};
3、多进程并行压缩代码
- 使用 webpack-parallel-uglify-plugin 插件
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
module.exports = {
···
plugins: [
new ParallelUglifyPlugin({
uglifyJS: {
output: {
beautify: false,
comments: false
},
compress: {
warnings: false,
drop_console: true,
collapse_vars: true
}
}
})
]
···
};
- 使用 uglify-webpack-plugin 插件,开启 parallel 参数(老的 webpack 版本使用,不支持压缩ES6的语法)
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
···
optimization: {
minimizer: [new UglifyJsPlugin()],
}
···
};
- 使用 terser-webpack-plugin 插件,开启 parallel 参数(新的 webpack 版本使用,支持压缩ES6的语法)
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
···
optimization: {
minimizer: [
new TerserPlugin({
parallel: true
})
],
}
···
};
4、分包
- 使用 html-webpack-externals-plugin,设置 externals
原理:将 react,react-dom 等公共基础包通过 cdn 方式引入,不打入 bundle 中
const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
module.exports = {
···
plugins: [
new HtmlWebpackExternalsPlugin({
externals: [{
module: 'react',
entry: 'https://unpkg.com/react@16/umd/react.development.js',
global: 'React'
}]
})
]
···
};
- 预编译资源模块,使用 DLLPlugin 分包,DllReferencePlugin对 manifest.json 引用
原理:将 react,react-dom 等公共基础包打包成一个文件
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: {
library: ['react','react-dom']
},
output: {
filename: '[name]_[chunkhash].dll.js',
path: path.resolve(__dirname,'./build/library'),
library: '[name]'
},
plugins: [
new webpack.DllPlugin({
name: '[name]_[hash]',
path: path.resolve(__dirname,'./build/library/[name].json')
})
]
};
module.exports = {
···
plugins: [
new webpack.DllReferencePlugin({
manifest: require('./build/library/library.json')
})
]
···
};
5、缓存(提升二次构建速度)
- babel-loader 开启缓存
module.exports = {
···
module: {
rules: [{
test: /\.js$/,
use: [ 'babel-loader?cacheDirectory=true' ]
}]
}
···
};
- terset-webpack-plugin 开启缓存
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
···
optimization: {
minimizer: [
new TerserPlugin({
parallel: true,
cache: true
})
],
}
···
};
- 使用 cache-loader 或者 hard-source-webpack-plugin
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
module.exports = {
···
plugins: [ new HardSourceWebpackPlugin() ]
···
};
6、缩小构建目标
- 尽可能少的构建模块
module.exports = {
···
module: {
rules: [{
test: /\.js$/,
use: [ 'babel-loader' ],
exclude: 'node_modules'
}]
}
···
};
- 减少文件搜索范围
(1)优化 resolve.modules 配置(减少模块搜索层级)
(2)优化 resolve.mainFields 配置
(3)优化 resolve.extensions 配置
(4)合理使用 alias
module.exports = {
···
resolve: {
modules: [path.resolve(__dirname, 'node_modules')],
mainFields: ['main'],
extensions: ['.js'],
alias: {
'react': path.resolve(__dirname, './node_modules/react/umd/react.production.min.js'),
'react-dom': path.resolve(__dirname, './node_modules/react-dom/umd/react-dom.production.min.js')
}
}
···
};
7、开启 tree-shaking
- 什么是 tree-shaking
通过工具"摇"我们的 js 文件,将其中用不到的代码"摇"掉,是一个性能优化的范畴。具体来说,在 webpack 项目中,有一个入口文件,相当于一棵树的主干,入口文件有很多依赖的模块,相当于树枝。实际情况中,虽然依赖了某个模块,但其实只使用其中的某些功能。通过 tree-shaking,将没有使用的模块摇掉,这样来达到删除无用代码的目的。
-
怎么使用
webpack 默认支持,.babelrc 文件设置modules: false
即可。(production mode 下默认开启) -
擦除无用 css
const glob = require('glob');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const PurgecssPlugin = require('purgecss-webpack-plugin');
module.exports = {
···
module: {
rules: [{
test: /\.css$/,
use: [ MiniCssExtractPlugin.loader, 'css-loader' ]
}]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name]_[contenthash:8].css'
}),
new PurgecssPlugin({
paths: glob.sync(`${path.join(__dirname, 'src')}/**/*`, { nodir: true }),
})
]
···
};
8、图片压缩
- 配置 image-webpack-loader
module.exports = {
···
rules: [{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
'file-loader',
{
loader: 'image-webpack-loader',
options: { disable: true }
},
],
}]
···
};