Webpack 5.110
Webpack 5.110 发布了。最亮眼的改进是 webpack 现在能告诉你打包出了什么问题:一套包含三十多个性能检查,可检测重复的包、无人使用的模块、瀑布式加载的 chunk、永远匹配不上的规则,以及其他以往需要借助插件或 bundle analyzer 才能发现的问题。
其次是内置压缩器现已同时支持 CSS 和 HTML,与 JavaScript 一道统一处理,每个重写操作都暴露为可配置项。加上自 5.107 以来逐步成熟的原生 CSS 支持,webpack 原生 CSS 管线与基于 loader 的方案之间的最后一道差距被彻底填补——这也是本次发布同步宣布弃用 css-loader、style-loader 和 mini-css-extract-plugin 的原因。
了解新增内容:
- Performance Hints
- CSS 和 HTML 压缩内置
- 原生 CSS 是未来方向
- 外部化已安装的包
- 跨平台的模块规则
- Tree Shaking 和作用域提升
- 服务端渲染
- HTML 改进
- 输出与 Library
- MultiCompiler
- 其他改进
- Bug 修复与性能优化
Performance Hints
`performance` 过去只做一件事:当资源或入口点的体积超出预算时发出警告。在 5.110 中,它变成了 webpack 在构建过程中发现的所有问题的汇总报告处。 这些检查分为两类。一类审视包的内容:重复引入的包、被多个入口点共同携带的模块、通过 barrel 文件拖入无人使用的代码、仅由单一模块持有的 chunk、无法真正延迟加载的 `import()` 调用。另一类审视配置:从未匹配过的 `module.rules` 条目、从未被 `resolve.alias` 解析的别名、没有任何模块读取的 `DefinePlugin` 键、从未被导入的 `externals` 请求、只在单一操作系统上能匹配到的 `test`。 webpack 已经拥有模块图、chunk 图、解析器的结果和规则集,因此每项检查都直接读取它所报告的对象,不存在凭空猜测。开启方式
所有检查默认关闭。performance.all 可一次性全部开启,显式设置的选项优先级更高:
export default {
// ...
performance: {
hints: "warning",
all: true,
},
};
审计项目时先用这个配置跑一遍。阅读完报告后,只保留对你有意义的检查项,其余保持关闭——因为部分检查需要遍历模块图,会消耗构建时间。
单个检查的开启方式同样如此:
Copyexport default {
// ...
performance: {
hints: "warning",
duplicatePackages: true,
unusedRules: true,
},
};
各检查项的作用
| 类别 | 检查项 |
|---|---|
| 重复携带的内容 | duplicatePackages、duplicateModules、entrypointOverlap |
| 未使用的代码 | unusedReexports、missingSideEffects、dynamicExports、scopeHoistingBailouts、legacyJavascript |
| Chunk 加载方式 | asyncChunkWaterfalls、redundantDynamicImports、tinyChunks、unsplitVendors、splitChunksCapped |
| Chunk 体积负担 | largeModules、inlinedAssets、embeddedSourceMaps、broadContexts |
| 代码隐患 | evalUsage、pureAnnotations、topLevelThis、mixedExports |
| 配置 | unusedRules、unusedAliases、unusedDefines、unusedExternals、osDependentRules、conflictingResourceHints |
| 构建本身 | cacheEffectiveness、hotspots、circularDependencies |
每一项都在 performance 下有文档说明,包括它会报告什么以及如何处理。
每个提示都会告知你发现了什么、代价是什么以及该如何处理。重复包报告列出具体版本和字节数;作用域提升报告按原因对避让情况分组,而非逐模块列举;hotspots 计时的是每个 loader、插件和钩子自身的同步代码耗时,而非等待时间,因此能指向真正慢的地方。
配置类检查不受 hints 开关限制。一条无匹配的规则或拼错的 external 是错误而非体积问题,因此只要该检查开启就会被报告。
仅输出到 stats
在从未开启过这些检查的项目里一下子打开二十项,会产生大量警告,在 CI 中甚至会导致构建失败。performance.hints: "stats" 将这些提示收集到 stats 中,而非作为警告或错误输出,这样你可以在处理报告的同时保持构建通过:
export default {
// ...
performance: {
hints: "stats",
all: true,
},
};
提示现在也在哈希计算之后生成,因此开启某项检查不会改变输出哈希值;条目并列时也会以稳定顺序报告。
内置 CSS 与 HTML 压缩
当启用optimization.minimize时,webpack 的默认压缩器现在会通过同一个 worker 池同时对 CSS、HTML 和 JavaScript 资源进行压缩。如果你已为这些资源配置了专属压缩器,webpack 会退让,交由你配置的压缩器处理。
两个压缩器在设计上都非常保守:它们只执行引擎无法区分的变换。
CSS 端会对 calc() 及其他数学函数在常量上进行折叠求值,将 box 模型的长手写为简写,用最短等价的写法表示每个颜色、数字、选择器和媒体查询,剔除被后续相同规则覆盖的死规则,并根据你的 browserslist 目标维护厂商前缀。
HTML 端会省略解析器可自动推断的标签,折叠不影响渲染的空白,统一属性引号和大小写,并通过各自独立的语法规则重写 style、token 列表、srcset、sizes 以及 JSON 格式的 <script> 内容。
按资源类型配置压缩器
optimization.minimize 现在可以接受一个对象,每个压缩器能执行的重写操作都是一个可独立关闭的选项:
export default {
// ...
optimization: {
minimize: {
javascript: { compress: { passes: 3 } },
css: {
// 此应用会在运行时读取自定义属性原文
rewriteCustomProperties: false,
},
html: {
collapseWhitespace: "smart",
sortAttributes: true,
sortTokenLists: true,
},
},
},
};
未在对象中命名的资源类型会使用其默认配置进行压缩,而将其设为 false 则会禁用该类型的压缩,其余类型仍正常运行。默认配置仅保留不会改变文档语义的变换;会改变脚本或选择器读取结果的操作(如 sortAttributes 或 removeRedundantAttributes)默认处于关闭状态,需要你显式开启。完整的选项列表可分别查阅 optimization.minimize.css 与 optimization.minimize.html 的文档。
CSS 和 HTML 也可以以美化格式输出,而非压缩,这正是构建调试时输出可读的原因。
原生 CSS 是未来方向
随着本次发布,webpack 内置的 CSS 流水线已覆盖原先 loader 栈的全部能力:CSS Modules(含作用域类名、id、关键帧、计数器和网格区域名称)、@import 与 url() 解析、自定义媒体查询、源映射、热模块替换、按 chunk 的代码分割,以及如今新增的浏览器感知前缀压缩。
这使得基于 loader 的配置变得多余,因此正在逐步废弃:css-loader、style-loader 和 mini-css-extract-plugin 已标记为弃用,推荐使用内置支持替代。它们仍可正常工作,webpack 也会在配置了这些 loader 时为其让路,因此本次发布不会破坏任何现有功能。但它们将不再获得新特性,对于所有新项目和新迁移,建议统一使用 experiments.css。
自 5.109 版本起,该支持的默认值为 'auto':除非已为 CSS 文件注册了 loader,否则会自动启用。这样现有项目会继续使用 loader,直到你主动移除;而新项目无需任何配置即可直接使用原生流水线。
此外,速度也更快。在 loader 方案中,每个样式表会在链式调用中的每个 loader 上被读取、解析和字符串化一次,然后作为 JavaScript 模块交还给 webpack 再次解析;而内置支持只需解析一次(作为 CSS),并全程保持 CSS 形式直达产物。CSS 在你的构建中占比越大,这一优势在墙钟时间上越明显——因此拥有数千个样式表的设计系统或组件库,从迁移中获得的收益远大于仅有少量样式表的普通应用。
迁移
你无需手动操作。现在有了 webpack codemods 仓库,其首个 codemod 专门用于此迁移:
Copynpx codemod @webpack/css-plugins-to-native-css
它会移除仅用于串联 style-loader、css-loader 和 MiniCssExtractPlugin.loader 的规则,并删除相