← 文章 / 未分类
js 6小时前 · 2026-09-14 14:55:37 · 1 阅读

Webpack 5.111

Webpack 5.111 来了!这个版本帮你省去了几件麻烦事:复制公共文件、为旧浏览器准备 CSS、找出不再需要打包的代码。ES module 输出也已转正,你可以从配置中移除实验性开关了。

此外还有更精简的 chunk 加载运行时、减少两个依赖、修复热更新和缓存问题,并为插件作者提供了一些新工具。下面来看看这次更新对项目有什么影响,以及从 5.110 升级需要改什么。

看看新内容:

ES Module 输出无需实验开关

以 ES module 形式发布应用或库?现在可以移除 experiments.outputModule,保留 output.module 即可。ESM 输出已经稳定,modulemodern-module 库类型以及 externalsType: "module" 也无需实验开关就能使用:

Copy
 export default {
-  experiments: {
-    outputModule: true,
-  },
   output: {
     module: true,
   },
 };

升级时需注意一个细节:如果仅设置了 experiments.outputModule: true,请补充 output.module: true Webpack 现已忽略旧版标志,仅保留它无法启用 ESM 输出。universaldenobun 目标仍默认使用 ESM;其他目标仍默认使用经典输出。

现在,将库类型设为 modulemodern-module 会自动开启 output.module。此类库仅以 ECMAScript 模块形式存在,因此无需重复配置:

Copy
export default {
  output: {
    library: {
      type: "module",
    },
  },
};

希望立即体验 Webpack 6 的默认行为?experiments.futureDefaults 现已包含 output.module。只要target支持,构建即可输出 ECMAScript 模块。以下三种情况仍会保持经典脚本输出:目标明确声明不支持模块(例如解析到 ie 11 或更低版本的 node10browserslist 查询结果)、库类型为从脚本中读取的 varumd,以及手动设置 output.module(该设置在双向中均优先)。

异步启动也得到改进。若入口使用顶层 await 加载配置,导入你打包代码的下游将等待该设置完成,失败时会接收到错误。此功能要求目标支持顶层 await。Webpack 会自动检测该支持,你也可在输出环境设置中通过 output.environment.topLevelAwait 进行覆盖。

ES 模块库与外部依赖

如果你发布的 ES 模块库重新导出了保持为外部的包,现在多项行为已修正:

Copy
export * from "lodash";
export { render } from "react-dom";
  • 实时绑定得以保留。由于 Webpack 发出的是原生重新导出而非一次性拷贝,外部包后续重新赋值的变量可被消费者看到。
    • externals 映射会被采用。 使用星号重新导出(star re-export)时,输出的请求将使用你配置的路径,而非源码中原始书写的路径。
    • 保留导入属性(Import attributes)。因此,像 export * from "./data.json" with { type: "json" } 这样的语句,其属性在输出的代码中会被保留。
    • 循环依赖不再导致栈溢出。此前,当两个模块通过外部模块(external)互相进行星号重新导出时,会引发此问题。
    • 对说明符(Specifiers)进行转义,使得包含特殊字符的请求在输出时能生成合法的字符串字面量。
      • 现在,一种此前会被错误输出的情况会作为报告显示出来:声明为数组的外部依赖(external)实际上是一个模块说明符加上一个属性路径。从该外部依赖执行 export * from 时,Webpack 之前会重新导出整个模块,而非你指定的那个属性。现在 Webpack 会将其报告为构建错误,以便你明确指定想要导出的项。

      • 配置中的文件 URL

      • 如果你将 Webpack 配置编写为 ES 模块,现在可以直接向 contextoutput.path 等路径选项传递 file: URL 字符串。这省去了额外使用 fileURLToPath() 进行转换的步骤:

      • 复制代码块:

      -import { fileURLToPath } from "node:url";
      -
       export default {
         output: {
      -    path: fileURLToPath(new URL("./dist/", import.meta.url)),
      +    path: new URL("./dist/", import.meta.url).href,
         },
       };

      • 你可以对 testinclude 等规则条件使用相同的方法。请记住使用 .href:在此处,Webpack 期望接收的是 URL 字符串,而不是 URL 对象。

      • 复制静态文件

      • 即使没有任何文件导入它们,你的 robots.txt、公共图片以及许可证文件也需要进入输出目录。借助 output.copy,你可以要求 Webpack 在构建过程中复制整个文件夹:

      • 复制代码块:

      export default {
        output: {
          copy: "public",
        },
      };

      • 这会将 public/ 的内容复制到你的输出目录中,并保留原有的文件夹结构。你不再需要为这种设置单独执行复制步骤。在监视模式(watch mode)运行期间编辑文件时,Webpack 会自动为你复制更新后的版本。这些文件还会出现在构建统计信息(build stats)中,并且在 output.clean 清理输出目录时会被保留。

      若需从多个位置复制文件,或指定文件的输出路径,可使用模式配置:

      Copy
      export default {
        output: {
          copy: [
            "public",
            { from: ["licenses/*.txt", "vendor/licenses/*.txt"], to: "licenses" },
            { from: "images", to: "img", filename: "[name].[contenthash][ext]" },
          ],
        },
      };

      你还可以筛选文件、转换内容,或保留文件权限和时间戳。Webpack 会在模式匹配无结果时发出警告;若复制操作会覆盖已生成的资源,则直接报错,助你尽早发现路径错误。如需更精细地控制复制时机及并发处理文件数,请使用内置的 CopyPlugin

      针对浏览器目标的 CSS 处理

      你可以编写现代 CSS,Webpack 负责适配旧版浏览器。使用 browserslist 目标时,内置的 CSS 压缩器会检测你支持的浏览器范围。lowerUnsupported 会将较新语法中受支持的部分改写为旧浏览器可识别的形式;colorFallbacks 则在新颜色声明前添加兼容性声明。

      这两项功能默认开启。此版本增强了语法覆盖范围,包括 inset、媒体查询范围以及 CSS 嵌套,并优化了压缩器对数学表达式和颜色的简化逻辑。你可以通过 optimization.minimize.css 调整具体设置:

      Copy
      export default {
        target: "browserslist",
        optimization: {
          minimize: {
            css: {
              lowerUnsupported: true,
              colorFallbacks: true,
            },
          },
        },
      };

      举例来说,如果目标浏览器列表中的某款浏览器不支持 inset,Webpack 会自动将其转换为四边分别指定的写法。以下是转换后的代码(已格式化以便阅读):

      Copy
       .panel {
      -  inset: 0;
      +  top: 0;
      +  right: 0;
      +  bottom: 0;
      +  left: 0;
       }

      如果你的项目需要更多控制权,可以启用以下选项:

      • unusedSymbols 允许移除你标记为未使用的类名、ID、关键帧和自定义属性。你需要在检查项目后提供具体名称,Webpack 不会自动识别这些未使用的符号。
      • pseudoClasses 选项适用于你借助脚本实现伪类行为的场景。例如,配置 { "focus-visible": "focus-visible" } 会将 :focus-visible 替换为 .focus-visible,你可以用脚本动态添加这个类名。
      • resolveCustomAtRules 允许压缩器处理未经过 Webpack CSS 解析器的样式表中的 @custom-media@custom-selector
      • rewriteDirSelector 会将不支持的 :dir() 重写为基于属性选择器的近似写法。仅当这种近似满足你的样式需求时才启用。
      • mergeDistantRules 即使中间隔着其他规则,也会合并声明一致的规则。该选项默认关闭,因为改变规则顺序可能会影响样式优先级。

      压缩功能现在更仔细地保留颜色值,特别是在其他 CSS 表达式读取颜色通道时;同时也确保 CSS 层级块的顺序正确。这些优化有助于生产环境的样式表现与你编写时一致。

      关于 CSS Modules,还有一个值得关注的修复:在 at-rule 前置部分(如 @keyframes 名称)中使用的 @value,现在只会进行作用域隔离一次。此前,通用的值处理逻辑会二次重写它,导致生成了动画无法匹配的双重命名。

      HTML 与嵌入内容

      如果你使用 Webpack 原生的 HTML 支持,本次发布进一步优化了生成的页面。压缩器会去除属性值中 URL 周围的空白,例如 hrefsrc。你还可以通过 mergeScripts 合并相邻的裸 script 标签,或通过 collapseBooleanAttributes: "all" 简化更多布尔属性。具体设置请参阅 optimization.minimize.html

      属性压缩现在依据属性值的语义而非源码中的拼写方式。过去,带引号的值会被重写,而不带引号的值则按原样保留,导致 method="GET" 被简化而 method=GET 没有。现在两者走相同的压缩路径,包括布尔属性的简化(

原始来源: js

评论 (0)