总览
webpack5 在 2020-10-10 已经正式发布,其优化方向:
- 使用持久化缓存提高构建性能
- 使用更优的算法和默认值改进长期缓存
- 优化 Tree Shaking 和代码生成以改善包大小
- 改善web平台兼容性
- 去除弃用功能
另外 webpack5 要求 node的最小的版本为 10.13.0
- 长期缓存
- 开发支持
- 支持崭新web平台特性
- 支持全新Node.js生态特性解析
- 构建优化
- 性能优化
- 未来计划
主要优化新特性:
1 功能清除
-
1.1 不再为Node.js模块自动引用 Polyfills
webpack5 之前的版本中,伪类大多数的Node.js模块运行在浏览器中,会在引用到node.js 模块的时候自动引入node.js核心模块的 polyfills,而 webpack 5 开始不再自动引入这些 polyfills,而会专注于前端模块兼容,提高 web 平台的兼容性,node模块本来就不是为浏览器设计的,这样还可以缩减体积,下例中,webpak4 webpack5 都将引入 crypto-js 模块
import Crypto from "crypto" console.log(Crypto.MD5('123'));
webpack4 的结果,1.45 MiB
webpack5 的结果,只会有2.31kb ,并且会报错
根据报错提示修改即可,webpack配置中加入module.exports = { .... resolve: { fallback: { // 以 crypto 举例, 如果使用到某些 api,可通过如下配置来兼容 "crypto": require.resolve("crypto-browserify"), // 完全没用到,不引入垫片,可通过如下配置来关闭 "crypto": false } }, }
仅输出 4.38kb
-
1.2 废弃 require.inclue 语法
废除require.include 语法,require.include 为webpack自身实现的,加载该模块但不立即执行,实现模块的预加载
2 长期缓存
-
2.1 新增长期缓存算法,确定的Chunk、模块ID和导出名称
webpack 5 之前加载异步模块时是以数字的形式递增命名,而某个模块发生变化,webpack重新打包,重新以顺序数字生成文件,导致缓存失效。
webpack5 加入长期缓存算法,该算法以确定性的方式为模块和分块分配短的(3 或 5 位)数字 ID, 这是包大小和长期缓存之间的一种权衡。在生成模式下默认开启chunkIds: "deterministic" moduleIds: "deterministic" mangleExports: "deterministic"
对文件内容进行内容级别的缓存。//main.js (async () => { await import('./a'); await import('./b'); await import('./c'); })()
webpack4
webpack5
-
2.2 真正的内容Hash
在使用 [contenthash] 时,webpack4 之前添加注释 空行等,都会进行重新加载打包,webpack5 之后做到了真正的内容hash,对于长期缓存有了更好的效果
3 开发支持
-
2.1 命名代码块ID
-
2.2 模块联邦
模块联邦是 webpack5 非常具有亮点的优化,它允许多个 webpack 构建产物一起工作,允许从指定的远程构建中导入,并以最小的限制来使用远程的 js bundle。
即是JS应用在运行过程中可以动态加载另一个应用的代码,并支持 CDN 共享依赖,不需要本地安装 npm 包
主要概念:- Remote: 方被依赖⽅,被 Host 消费的 webpack 构建
- Host:依赖⽅,消费其他 Remote 的 webpack 构建
任一个应用可以是Remote、Host、同时为Remote和Host
模块联邦的实现主要通过
ModuleFederationPlugin
来实现,将多个应用结合起来
- name:必须,唯⼀ ID,作为输出的模块名,使⽤的时通过 name/{name}/name/{expose} 的⽅式使⽤
- library:必须,其中这⾥的 name 为作为 umd 的 name;
- remotes:可选,表示作为 Host 时,去消费哪些 Remote;
- shared:可选,优先⽤ Host 的依赖,如果 Host 没有,再⽤⾃⼰的;
- main.js:应⽤主⽂件
- remoteEntry.js:作为 remote 时被引的⽂件一个小demo如下
demo中有两个小项目,host 和 remote
host 中引用header组件
webpack配置中引入ModuleFederationPlugin 插件new ModuleFederationPlugin({ // 提供给其他服务加载的文件 filename: "remoteEntry.js", // 唯一ID,用于标记当前服务 name: "host", library: { type: "var", name: "host" }, // 需要暴露的模块,使用时通过 `${name}/${expose}` 引入 exposes: { './Header': "./src/components/Header.vue", } })
将Host 组件在 3000端口启动
而在remote 中引入 host中的header组件,import 组件时注意使用 host中配置的ModuleFederationPlugin 插件中 name 属性拼接exposes 中组件即可
在8081端口启动,可以看到成功引用了 header组件