接上一篇 👉 :Webpack5 学习 - 基础篇
优化篇
更新至最新版本
使用最新的 webpack 版本。将 Node.js 更新到最新版本,也有助于提高性能。除此之外,将 package 管理工具(例如 npm
或者 yarn
)更新到最新版本,也有助于提高性能。较新的版本能够建立更高效的模块树以及提高解析速度。
减少 loader 应用范围
配置 loader ,通过使用 include
和 exclude
指定 loader 的作用目录或者需要排除的目录, exclude
优先级更高
include
:符合条件的模块进行解析exclude
:排除符合条件的模块,不解析
例如在配置 babel 的时候
const path = require('path');
module.exports = {
module: {
rules: [
//babel
{
test: /\.js$/,
include: path.resolve(__dirname, '../src'),
exclude: /(node_modules|bower_components)/, //不转换的文件
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-react','@babel/preset-env']
}
}
}
],
},
}
优化 resolve 配置
1. alias 配置别名
const path = require('path')
module.exports = {
resolve: {
// 配置别名
alias: {
'~': path.resolve(__dirname, '../src'),
'@': path.resolve(__dirname, '../src'),
'components': path.resolve(__dirname,'../src/components'),
}
},
}
配置完成之后,引入文件可以这样写
import '~/style.css'
import icon from '@/assets/icon.png'
import Hello from "components/Hello";
2. extensions 解析文件
extensions 表示需要解析的文件类型列表。如果用户引入模块时不带扩展名,那么 webpack 就会按照 extensions 配置的数组从左到右的顺序去尝试解析模块
- 高频文件后缀名放前面;
- 手动配置后,默认配置会被覆盖
webpack.common.js
:
const config = {
//...
resolve: {
//extensions: ['.js', '.json', '.wasm'], //默认配置
extensions: ['.ts', '...'], //保留默认配置
},
};
3. modules
告诉 webpack 解析模块时应该搜索的目录,指定目录可缩小 webpack 解析范围,加快构建速度。
webpack.common.js
:
module.exports = {
modules: [
path.resolve(__dirname, '../src'),
'node_modules'
]
}
4. module.noParse
精准过滤不需要解析的文件,防止 webpack 解析那些任何与给定正则表达式相匹配的文件。忽略的文件中 不应该含有 import
, require
, define
的调用,或任何其他导入机制。忽略大型的 library 可以提高构建性能。
module.exports = {
//...
module: {
noParse: /jquery|lodash/,
},
};
5. resolveLoader
与 resolve
对象的属性集合相同, 但仅用于解析 webpack 的 loader 包。
module.exports = {
//...
resolveLoader: {
modules: ['node_modules'],
extensions: ['.js', '.json'],
mainFields: ['loader', 'main'],
},
};
6. symlinks
如果项目不使用 symlinks(例如 npm link
或者 yarn link
),可以设置 resolve.symlinks: false
,减少解析工作量。
webpack.common.js
配置方式如下:
module.exports = {
resolve: {
//是否将符号链接(symlink)解析到它们的符号链接位置(symlink location)。
//启用时,符号链接(symlink)的资源,将解析为其 *真实* 路径,而不是其符号链接(symlink)的位置。
//注意,当使用创建符号链接包的工具(如 `npm link`)时,这种方式可能会导致模块解析失败。
symlinks: false,
},
}
外部扩展(Externals)
防止将某些 import
的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies) 。
该方法可以在打包时不将外链引用的第三方模块不打包到最终文件中,可以减少打包文件的体积
例如,从 CDN 引入 jQuery,而不是把它打包:
index.html
<script
src="https://code.jquery.com/jquery-3.1.0.js"
integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
crossorigin="anonymous"
></script>
webpack.config.js
module.exports = {
//...
externals: {
jquery: 'jQuery',
},
};
这样就剥离了那些不需要改动的依赖模块,换句话,下面展示的代码还可以正常运行:
import $ from 'jquery';
$('.my-element').animate(/* ... */);
IgnorePlugin
防止在 import
或 require
调用时,生成以下正则表达式匹配的模块:
requestRegExp
匹配(test)资源请求路径的正则表达式。contextRegExp
匹配(test)资源上下文(目录)的正则表达式。
避免一些模块引入,从而节省打包的体积
例如:moment会支持多语言,如何只引入中文模块?
$ npm i moment -S //安装
配置 IgnorePlugin:
// 引入 webpack
const webpack = require('webpack')
const config = {
...
plugins:[ // 配置插件
...
// 忽略 moment 下的全部 /locale目录
new webpack.IgnorePlugin({
resourceRegExp: /^\.\/locale$/,
contextRegExp: /moment$/,
}),
]
};
按需引入
// 业务代码中动态引入语言包
import 'moment/locale/zh-cn'
缓存 cache
webpack cache 来缓存生成的 webpack 模块和 chunk,改善构建速度
//内存缓存
//dev模式下默认。编译缓存将保存在内存中。
module.exports = {
cache: true, // 等价于cache: { type: 'memory' },
}
//文件缓存
//每次编译的结果都会序列化保存到 node_modules/.cache 目录下,
//当下次编译启动时会从 cache 反序列化加载,减少对机器内存的压力
module.exports = {
cache: {
type: 'filesystem',
},
}
压缩 CSS
$ npm i css-minimizer-webpack-plugin -D
修改 webapck.config.js
配置
// 压缩css
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const config = {
// ...
optimization: {
// 默认仅生产环境开启 CSS 优化,minimize 设置为 true 开发环境下也启用
minimize: true,
minimizer: [
// 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释
// `...`,
new CssMinimizerPlugin(),
],
},
// ...
}
清除无用的 CSS
purgecss-webpack-plugin 会单独提取 CSS 并清除用不到的 CSS
$ npm i purgecss-webpack-plugin -D
添加配置
const PurgecssWebpackPlugin = require('purgecss-webpack-plugin')
const glob = require('glob'); // 文件匹配模式
压缩 JS
👉 传送门
webpack v5 开箱即带有最新版本的 terser-webpack-plugin
。如果你使用的是 webpack v5 或更高版本,同时希望自定义配置,那么仍需要安装 terser-webpack-plugin
。如果使用 webpack v4,则必须安装 terser-webpack-plugin
v4 的版本。
$ npm i terser-webpack-plugin -D //安装
配置
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
optimization: {
minimize: true,
minimizer: [new TerserPlugin()],
},
};
工具插件
查看编译进度
插件:progress-bar-webpack-plugin
$ npm i progress-bar-webpack-plugin -D //安装插件
配置 webpack.common.js
:
const chalk = require('chalk')
const ProgressBarPlugin = require('progress-bar-webpack-plugin')
module.exports = {
plugins: [
// 编译进度条
new ProgressBarPlugin({
format: `:msg [:bar] ${chalk.green.bold(':percent')} (:elapsed s)`
})
],
}
编译即可看到效果
查看编译速度
插件: speed-measure-webpack-plugin
通过插件,可以看到各个 loader、plugin 的构建时长,后续可针对耗时 loader、plugin 进行优化。
$ npm i speed-measure-webpack-plugin -D //安装插件
配置 webpack.dev.js
:
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
module.exports =smp.wrap(merge(common, {
mode: 'development', // 开发模式
// ...webpack config...
}));
不兼容,需要进行降级处理
查看打包体积
通过插件,查看打包后生成的 bundle 体积分析,将 bundle 内容展示为一个便捷的、交互式、可缩放的树状图形式。帮助我们分析输出结果来检查模块在何处结束。
$ npm i webpack-bundle-analyzer -D //插件安装
配置 webpack.prod.js
:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = merge(common, {
mode: 'production',// 生产模式
plugins: [
new BundleAnalyzerPlugin() // 打包体积分析
],
})