了解 Webpack 5

了解 Webpack 5

年初 Webpack 核心团队有过一次关于 Webpack 5 的演讲,讲述了 Webpack 5 的开发进度以及即将带来的新特性。

目前已经可以安装 Webpack 5 了,但官网最新稳定版本还是 Webpack 4。

1
2
// 安装方式
npm install -D webpack@next webpack-cli

下面简单介绍下 Webpack 5 主要变更

Removed Deprecated Items

在 Webpack 4 中已经被抛弃但是仍然可以被使用的特性,将在 Webpack 5 中彻底被废弃。

另外,在 Webpack 5 中 IgnorePlugin 和 BannerPlugin 插件必须传递 options 参数对象。

Automatic Node.js Polyfills Removed

Webpack 为了能够实现在浏览器中运行 Node 模块的功能,会添加大量的 Polyfill 脚本,这些脚本最终会添加到最后的编译代码中。现在,越来越多的脚本采用前端模块进行编写,也就没必须增加这些 Polyfill 脚本了。

Webpack 5 开始将不再自动添加 Polyfill 脚本了,可以有效减少最终编译代码的大小。

Persistent Caching

在 Webpack 编译过程中,如果某个文件发生变化,那么 Webpack 会从 entry 开始,从新递归查找所依赖的模块,然后重新编译。

Webpack 5 中采用持久化缓存来优化整个编译流程:当检测到文件发生变化时,只会对发生变更的文件进行编译,从而提高编译效率。

按演讲中的测试效果,16000 模块的单页应用使用持久化缓存,编译速度可以提高 98%。

默认情况下,持久化缓存是不开启的,可以通过下面的配置启用持久化缓存:

1
2
3
4
5
6
7
8
9
10
11
12
cache: {
// 1. Set cache type to filesystem
type: "filesystem",

buildDependencies: {
// 2. Add your config as buildDependency to get cache invalidation on config change
config: [__filename]

// 3. If you have other things the build depends on you can add them here
// Note that webpack, loaders and all modules referenced from your config are automatically added
}
}

缓存文件存储在 node_modules/.cache/webpack.pnp/.cache/webpack 中。

Named Chunk IDs

在 Webpack5 中开发模式将默认启用全新的 Chunk ID 命名算法,提高 Chunk 名称的可读性。Module ID 由其相对的上下文路径决定,Chunk ID 由其内容决定。

也可以通过下面的配置开启或禁用新的命名算法:

1
2
3
4
5
// 开启
optimization: { chunkIds: 'named' }

// 关闭
optimization: { chunkIds: 'natural' }

Deterministic Chunk and Module IDs

为了帮助长期缓存(long term caching),Webpack 5 增加了新的算法。新算法会以确定的方式为 Module、Chunk 分配一个非常短(3~4 个字符)的数字 ID。因此,对于没有发生变化的 Module 或 Chunk,它们对于的 ID 也不会发生变化,仍然可以被浏览器缓存,提高资源加载的性能。

可以通过下面的配置开启或禁用新的算法:

1
2
3
4
5
// 开启
optimization: { chunkIds: 'deterministic' }

// 关闭
optimization: { chunkIds: 'size' }

Tree-shaking Optimize

Webpack 5 可以追踪分析嵌套模块的再输出,移除未使用的代码。

下面代码中编译后 b 将会被移除:

1
2
3
4
5
6
7
8
9
10
11
// 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);

另外,Webpack 5 新增了优化选项 optimization.innerGraph,可以分析模块内部输入、输出的依赖关系,来判断哪些代码未使用。

1
2
3
4
5
6
7
8
9
import { something } from "./something";

function usingSomething() {
return something;
}

export function test() {
return usingSomething();
}

上面的代码,如果 test() 未被使用,那么 ./something 将会在 Tree-shaking 过程中被移除。

Improved Code Generation

Webpack 4 最终编译生成的代码对应的版本是 ES5,Webpack 5 中可以指定编译后的代码版本为 ES5 或 ES6/ES2015。

1
output: { ecmaVersion: 5 | 2015 }

SplitChunks and Module Sizes

Webpack 支持 splitChunks 给不同的文件类型设定文件最小、最大的拆分限制条件。

1
2
3
4
minSize: {
javascript: 30000,
style: 50000,
}

Minimum Node.js Version

Webpack 5 要求 Node 最低版本为 Node 8.

参考