webpack进阶教程之性能优化篇
背景:打包的时候JS文件很多,所以主要的是优化对JS文件的打包速度
一 Oneof的使用
隶属于减少编译范围、编译步骤等,以此来优化打包性能
// 以上一篇文章为例子
// 例子代码
/*
正常来讲,所有文件在执行的时候,都要将loader中的rules过一遍,如果符合,就被对应loader处理,然后接着往下执行别的rules。如果不符合,也会执行所有的rules。
举个例子: 在rules 中有4个对象,当匹配到 .css文件以后,会进行打包,但操作完成以后,会接着往下执行后面的几个匹配规则。同样当匹配到 .less以后,依然会接着往下执行。
oneOf的作用:oneOf里面的loader只匹配一个,避免每个文件都被所有loader过一遍。
使用oneOf以后,匹配到对应文件后,别的loader就不会执行了。提升了效率
*/
const path = require("path");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "main.js",
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
],
},
plugins: [],
mode: "development",
};
// 使用oneOf。 oneOf里面的loader只匹配一个,避免每个文件都被所有loader过一遍
const path = require("path");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "main.js",
},
module: {
rules: [
{
oneOf: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
]
}
],
},
plugins: [],
mode: "development",
};
二 include与exclude(二者用一个即可)
隶属于减少编译范围、编译步骤等,以此来优化打包性能
/*
include 表示哪些目录中的 .js 文件需要进行 babel-loader
exclude 表示哪些目录中的 .js 文件不要进行 babel-loader
*/
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true, // 自动将上次打包目录资源清空
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "src"),
}),
],
mode: "development",
};
三 Cache缓存的使用
隶属于使用 Cache 提升构建性能
/*
Cache:首次全部加载,加载完成以后,将加载内容存储,以后的加载都从存储中获取,而不需要重新加载。
*/
/*
type: 'filesystem' : 它能够将首次构建结果持久化到本地文件系统,在下次执行构建时跳过一系列解析、链接、编译等非常消耗性能的操作,直接复用 module、chunk 的构建结果。
*/
module.exports = {
//...
cache: {
type: 'filesystem'
},
//...
};
四 多进程打包
缓存的本质是复用,而多进程(并行)的本质则是在同一时间内并发执行多个操作。
使用方式:
npm install thread-loader
module.exports = {
module: {
rules: [{
test: /\.js$/,
use: [
'thread-loader'
],
}],
},
};
五 tree-shaking
隶属于移除无效代码,精简打包体积
/*
Webpack5 已经默认开启了这个功能,无需其他配置
移除 JavaScript 中的没有使用上的代码
*/
六 减少bable体积
隶属于移除无效代码,精简打包体积
使用:
npm i @babel/plugin-transform-runtime
/*
Babel 为编译的每个文件都插入了辅助代码,使代码体积过大!
使用插件,缩小体积
*/
module.exports = {
module: {
rules: [{
test: /\.js$/,
use: [
{
loader: 'thread-loader', //使用多进程打包
options:{
worker: threadsNum // 多进程数量,可在开头用node.js 方式获取,然后在这里配置
}
},
{
loader: 'babel-loader', //使用多进程打包
options:{
cacheDirectory:true, // 开启babel编译缓存
cacheCompression:false, // 缓存文件不要压缩
plugins:["@babel/plugin-transform-runtime"] // 减少代码体积
}
}
],
}],
},
};
七 减少图片体积
隶属于缩小代码体积
一定要用cnpm 要不然报错,下载不下来,妈的。
cnpm install image-webpack-loader -D
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
type: 'asset', // asset 资源类型可以根据指定的图片大小来判断是否需要将图片转化为 base64
generator: {
filename: 'img/[hash][ext][query]' // 局部指定输出位置
},
parser: {
dataUrlCondition: {
maxSize: 8 * 1024 // 限制于 8kb
}
},
// 图片压缩的配置
use: [
// image-webpack-loader需要用cnpm安装否则容易报错
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true
},
// optipng.enabled: false will disable optipng
optipng: {
enabled: false
},
pngquant: {
quality: [0.65, 0.9],
speed: 4
},
gifsicle: {
interlaced: false
},
// the webp option will enable WEBP
webp: {
quality: 75
}
}
}
]
},
八 code split 代码分割
隶属于缩小代码体积
/*
webpack会把所有的JS打包到一个JS文件中,体积太大。可以使用代码分割,把一个JS文件分割成多个JS文件
配置:
optimization: {
splitChunks: {//这里配置使用这个插件
chunks: "all"
}
}
*/
entry: {
index: "./src/index.js", //设置打包入口,
another: "./src/another_module.js"
},
output: {
path: path.resolve(__dirname, "dist"), //设置打包的出口,需要是绝对路径,而__dirname是node的一个全局变量,记录当前文件的绝对路径
filename: "[name]_bundle.js", //设置打包出来的js的文件名
clean: true, //清除上次打包出来的文件
assetModuleFilename: "images/[contenthash][ext]" //自定义asset module资源打包后的路径和名字
},
optimization: {
splitChunks: {//这里配置使用这个插件
chunks: "all"
}
}