笔者使用了 webpack5
将项目进行了重构,并全程使用的 webpack-chain
来配置 webpack
,每个功能也都是独立文件,可单独使用。因此该项目的配置可以在任何项目中被使用。此项目可实战亦可当成 webpack
手册来学习。我开发这个项目的目的就是无论你是新手还是有经验的大佬都可以从中有所收获。此项目为想学 webpack
的同学提供了很好的实战平台,每一个 插件
每一个 loader
都会有详细的讲解及使用背景。
为了节省大家时间,提升学习效率,我想要将所有 webpack
相关的系列都集成在这里,这里的每一个优化都是经过我反复推敲实践而来,也会吸取一些优秀的开源库来完善它,此项目将长期维护,也诚挚欢迎所有人参与到该项目当中,一起成为该项目的共建者!
项目地址:https://github.com/luoxue-victor/webpack-box
因为本文是使用 webpack5
进行了重构,那我就先将第 14 课时放在前面讲了
本文目录
课时 14:升级 webpack5
课题 10:添加 eslint 并开启自动修复
课题 11:添加 stylelint 并开启自动修复
课题 12:添加 tslint 并开启自动修复
课题 13:配置别名
课时 15:定义通用变量
课时 16:严格区分路径大小写
课时 17:加载资源 images、svg、media、fonts
课时 18:设置全局样式
vscode 配置
prettier 配置
接下来计划去做的 TODO https://github.com/luoxue-victor/webpack-box/issues
课时 14:升级 webpack5
本章主要将项目升级到 webpack5,先踩一下坑。把踩坑的经过给大家分享一下。
webpack5 更像是一个黑盒了,好多之前必须要用插件来完成的工作,现在 webpack5 内部已经被集成了,开箱即用。webpack5 主要为了优化编译速度、更多的默认配置(内置了更多的配置)、更好的代码生成、为将来 webpack 走的更远做铺垫。
本章概要
webpack5 做了哪些事情?
升级 webpack5
编译速度对比
webpack4 到 webpack5 的变化
webpack5 做了哪些事情?
使用长期缓存提升编译速度
使用更好的算法和默认值来改善长期缓存
通过更好的 Tree Shaking 和 Code Generation 来改善 bundle 大小
重构内部结构,在不引入任何重大更改的情况下实现 v4 的功能
通过引入重大更改来为将来的功能做准备,以使我们能够尽可能长时间地使用 v5
升级 webpack5
本教程可以通过脚手架命令一键升级/降级
webpack-box upgrade 5/4
主要升级了两个插件,其他使用到的模块都已经被兼容,html-webpack-plugin
插件因为涉及到热更新,目前热更新的 bug 还没有修复,所以大家切换到 webpack5
之后的第一次编译可以成功,但是保存后的再次编译会报错(这点我会持续关注,一旦修理立即更新版本)
package.json
{
"html-webpack-plugin": "^4.0.0-beta.11",
"webpack": "^5.0.0-beta.9"
}
编译速度对比
webpack-box build index
Version: webpack 4.41.2
以下是使用了 cache-loader
第一次
4216ms
第二次
2781ms
第三次
2827ms
第四次
2797ms
Version: webpack 5.0.0-beta.9
使用了 持久缓存
第一次
3567ms
第二次
2602ms
第三次
2609ms
第四次
2582ms
可以看出来 webpack5
使用持久缓存的情况下比 webpack4
使用 cache-loader 的编译速度快了 100ms ~ 200ms
,所以以后就没有必要使用 cache-loader,webpack5 提供了更好的算法跟更优秀的缓存方案
webpack4 到 webpack5 的变化
1. cache-loader 不再需要
使用持久性缓存时,您不再需要缓存加载器。与 babel cacheDirectory 相同。
2. html-webpack-plugin 问题
一些错误并修复 error
Cannot add property htmlWebpackPluginAlterChunks, object is not extensible
安装 4.x 版本可修复
npm i html-webpack-plugin@4.0.0-beta.11
Cannot read property 'get' of undefined
未修复
第一次编译生效,保存之后会报错,webpack5
对热更新进行了重写,导致 html-webpack-plugin
不兼容,原因可查[1]
3. 动态加载的文件终于有名字了,不再是 id,而是改为项目路径的拼接
可以使用 optimization.chunkIds 进行修改
点击看文档[2]
module.exports = {
//...
optimization: {
chunkIds: "named"
}
};
// 链式修改
config.optimization.set("chunkIds", "natural");
动态模块的 name 是路径 + 下划线dist/index/

4. 嵌套 tree-shaking
如下,在 webpack4 中 a、b 都会被打包进 bundle 中,webpack5 会对嵌套的无用代码也会删除掉,也就是说 b 并不会被打包进 bundle 中了,因为 b 并没有被使用到
// inner.js
export const a = 1;
export const b = 2;
// module.js
import * as inner from "./inner";
export { inner };
// user.js
import * as module from "./module";
console.log(module.inner.a);
5. 内部模块 tree-shaking
webpack5 会检查都模块内部的方法是否被使用,如果没有被使用的话,那么会把模块内部调用的方法也会被删除
但是前提是你要知道这些代码是无副作用的,不然很有可能将你的代码删掉,比如你要写一个组件,而你库里并没有使用它,那么就有可能在打包的时候被 tree-shaking 了
使用它您需要在 package.json
中配置 "sideEffects": false
,并且设置 optimization.usedExports
为 true
// package.json
{
"sideEffects": false
}
// config/optimization.js
config.optimization.usedExports(true);
代码演示
import { something } from "./something";
function usingSomething() {
return something;
}
export function test() {
return usingSomething();
}
如果外部模块没有使用 test 方法的话,那么 usingSomething、something 也会在 bundle 中被删除
6. 改进代码生成
告诉 webpack webpack 生成代码的最大 EcmaScript 版本
webpack4
仅能支持到 ES5,webpack5
支持 ES5 跟 ES6
ecmaVersion
的取值范围 5 ~ 11 或 2009 ~ 2020,webpack5 默认采用最小值 5
config.output.set("ecmaVersion", 6);
7. SplitChunks and Module Sizes
webpack5 可以根据不同类型的文件分别设置 splitChunks 打包的尺寸,默认情况下只针对 javascript 进行分离打包
config.optimization.splitChunks({
minSize: {
javascript: 30000,
style: 50000
}
});
8. 持久缓存
webpack5 提供了两种缓存方式,一种是持久缓存将文件缓存在文件系统,另一种是缓存在内存里
// ty