webpack如何做到性能优化
1.代码分离
1.1 入口起点
使用entry配置手动分离代码;也就是多入口文件来实现代码分离;
注意:多入口起点的话就要注意重复引入,导致体积过大的问题,可配置共享解决此问题
module.exports = {
mode: 'development',
devtool: false,
// entry: './src/index.js',
entry: {
index: {
import: './src/index.js',
dependOn: 'shared' //可共享
},
main: {
import: './src/main.js',
dependOn: 'shared' //可共享
},
shared: ['axios'] //配置共享的模块
},
output: {
path: path.resolve(__dirname, './build'),
// placeholder
filename: '[name]-bundle.js', //[name]也就是entry对应的名称
clean: true //每次打包的前先清理之前的打包文件
},
}
1.2自定义分包
另外一种分包的模式是splitChunk,它底层是使用SplitChunksPlugin来实现的:
因为该插件webpack已经默认安装和集成,所以我们并不需要单独安装和直接使用该插件;
只需要提供SplitChunksPlugin相关的配置信息即可;
// 优化配置
optimization: {
// 设置生成的chunkId的算法
// development: named
// production: deterministic(确定性)
// 早期webpack4中使用: natural
chunkIds: 'deterministic',
// runtime的代码是否抽取到单独的包中(早Vue2脚手架中)
runtimeChunk: {
name: "runtime"
},
// 分包插件: SplitChunksPlugin
splitChunks: {
chunks: "all",//包括异步引入和同步引入,而async只仅仅针对异步的
// 当一个包大于指定的大小时, 继续进行拆包
maxSize: 20000,//当分出来的包又大于20000,则继续拆包
// // 将包拆分成不小于minSize的包
minSize: 10,//最小的包体积
// 自己对需要进行拆包的内容进行分包
cacheGroups: {
utils: {
test: /utils/,
filename: "[id]_[hash:6]_utils.js" //hash是哈希值
},
vendors: {
// /node_modules/
// window上面 /\
// mac上面 /
test: /[\\/]node_modules[\\/]/,
filename: "[id]_vendors.js"
}
}
},
// 代码优化: TerserPlugin => 让代码更加简单 => Terser
minimizer: [
// JS代码简化
new TerserPlugin({
extractComments: false
})
// CSS代码简化
]
},
1.3动态导入
通过模块的内联函数调用来分离代码;(动态路由)
2. 预加载preload和prefetch
preload chunk 会在父 chunk 加载时,以并行方式开始加载。prefetch chunk 会在父 chunk 加载结束后开始加载。
preload chunk 具有中等优先级,并立即下载。prefetch chunk 在浏览器闲置时下载。
preload chunk 会在父 chunk 中立即请求,用于当下时刻。prefetch chunk 会用于未来的某个时刻。
3.cdn
国际上使用比较多的是unpkg、JSDelivr、cdnjs;
国内也有一个比较好用的CDN是bootcdn;
4.提取css
如果用的是css-loader和style-loder,那么css代码是集成到js文件里面的,不是单独的css;需要做如下的配置;
npm install mini-css-extract-plugin -D
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')
const { ProvidePlugin } = require('webpack')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
mode: 'development',
devtool: false,
// entry: './src/index.js',
entry: './src/main.js',
output: {
clean: true,
path: path.resolve(__dirname, './build'),
// placeholder
filename: 'js/[name]-bundle.js',
// 单独针对分包的文件进行命名
chunkFilename: 'js/[name]_chunk.js',
// publicPath: 'http://coderwhycdn.com/'
},
resolve: {
extensions: ['.js', '.json', '.wasm', '.jsx', '.ts']
},
devServer: {
static: ['public', 'content'],
port: 3000,
compress: true,
proxy: {
'/api': {
target: 'http://localhost:9000',
pathRewrite: {
'^/api': ''
},
changeOrigin: true
}
},
historyApiFallback: true
},
// 优化配置
optimization: {
// 设置生成的chunkId的算法
// development: named
// production: deterministic(确定性)
// webpack4中使用: natural
chunkIds: 'deterministic',
// runtime的代码是否抽取到单独的包中(早Vue2脚手架中)
runtimeChunk: {
name: "runtime"
},
// 分包插件: SplitChunksPlugin
splitChunks: {
chunks: "all",
// 当一个包大于指定的大小时, 继续进行拆包
// maxSize: 20000,
// // 将包拆分成不小于minSize的包
// minSize: 10000,
minSize: 10,
// 自己对需要进行拆包的内容进行分包
cacheGroups: {
utils: {
test: /utils/,
filename: "js/[id]_utils.js"
},
vendors: {
// /node_modules/
// window上面 /\
// mac上面 /
test: /[\\/]node_modules[\\/]/,
filename: "js/[id]_vendors.js"
}
}
},
// 代码优化: TerserPlugin => 让代码更加简单 => Terser
minimizer: [
// JS代码简化
new TerserPlugin({
extractComments: false
})
// CSS代码简化
]
},
module: {
rules: [
{
test: /\.jsx?$/,
use: {
loader: "babel-loader",
}
},
{
test: /\.ts$/,
use: 'babel-loader'
},
{
test: /\.css$/,
use: [
// 'style-loader', 开发阶段
MiniCssExtractPlugin.loader, // 生产阶段
'css-loader'
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html'
}),
// 完成css的提取
new MiniCssExtractPlugin({
filename: 'css/[name].css',
chunkFilename: 'css/[name]_chunk.css'
})
]
}
5.js压缩丑化代码terser(减少体积)
在webpack中有一个minimizer属性,在production模式下,默认就是使用TerserPlugin来处理我们的代码的;
在webpack中有一个minimizer属性,在production模式下,默认就是使用TerserPlugin来处理我们的代码的;
相关文档
https://github.com/terser/terser#compress-options
https://github.com/terser/terser#mangle-options
6.css压缩
css-minimizer-webpack-plugin
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
new CSSMinimizerPlugin({
// parallel: true
})
7.css tree Shaking
npm install purgecss-webpack-plugin -D
const glob = require('glob')
const { PurgeCSSPlugin } = require('purgecss-webpack-plugin')
plugins: [
// 完成css的提取
new MiniCssExtractPlugin({
filename: 'css/[name].css',
chunkFilename: 'css/[name]_chunk.css'
}),
// 对CSS进行TreeShaking
new PurgeCSSPlugin({
paths: glob.sync(`${path.resolve(__dirname, '../src')}/**/*`, { nodir: true }),
safelist: function() {
return {
standard: ["body"]
}
}
})
]
8.文件压缩
npm install compression-webpack-plugin -D
plugins: [
// 完成css的提取
new MiniCssExtractPlugin({
filename: 'css/[name].css',
chunkFilename: 'css/[name]_chunk.css'
}),
// 对CSS进行TreeShaking
// new PurgeCSSPlugin({
// paths: glob.sync(`${path.resolve(__dirname, '../src')}/**/*`, { nodir: true }),
// safelist: function() {
// return {
// standard: ["body"]
// }
// }
// }),
// 作用域提升
new webpack.optimize.ModuleConcatenationPlugin(),
// 对打包后的文件(js/css)进行压缩
new CompressionPlugin({
test: /\.(js|css)$/,
algorithm: 'gzip'
})
]