DEBUG.WIKI
晚安云;香港 CN2 ¥15/月
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
搬瓦工;先看线路,再选 VPS;CN2 GIA · 对应线路套餐;查看线路 →

webpack 二次打包 Jest 后报 __webpack_modules__[moduleId] is not a function

webpack 二次打包 Jest 发布文件后,内外层 require 名称混淆可能让模块 ID 进入错误模块表。检查箭头函数作用域,并核对 5.106.0 修复。

浏览器测试或扩展激活时,代码进入 @jest/expect-utils 就报 __webpack_modules__[moduleId] is not a function,栈里同时有 __nested_webpack_require_*__ 和外层 webpack require。项目使用 webpack 5.103.0 至已确认失败的 5.105.4 组合时,应检查已经打包过的依赖被再次打包后,内外层运行时名称是否混淆。

这条具体回归已在 webpack 5.106.0 正式版修复。它不是说所有相同错误都来自 Jest,也不表示报错范围内每个版本、每个构建配置都会触发;关键证据是产物中的作用域和模块表对应关系。

模块 ID 被交给了另一份模块表

Jest 的部分发布文件本身含有 webpack 运行时。应用再次打包它时,会同时存在外层应用模块和内层依赖模块。两边都可能使用名为 __webpack_require__ 的函数,但处理的模块 ID 并不是同一套。

触发形态包括依赖内部的箭头函数参数:

// 仅说明已打包依赖的结构,不是需要加入应用的运行时代码。
(__webpack_module, __webpack_exports, __webpack_require__) => {
  // 此处还有由外层构建转换的 require 调用。
};

webpack 的兼容处理本应正确区分并重命名嵌套 require。受影响判断遗漏了箭头函数作用域的一种状态,使已记录的重命名信息被覆盖。某条本应交给外层运行时的调用,随后可能落到内层运行时;内层模块表没有那个 ID,最终在调用位置报“不是函数”。

先保留一份未压缩的失败产物,沿错误位置检查调用使用的函数、参数和模块表。不要只搜索到一个 __webpack_require__ 就全局替换,它可能本来就是正确的运行时入口。

让构建器修复作用域处理

更新到包含修复、且符合现有 loader 和插件支持范围的 webpack 版本。5.106.0 的正式兼容插件将箭头函数作用域与真正的顶层作用域区分开,不再在这个位置覆盖嵌套名称信息。

版本应在实际构建依赖中生效。Karma、框架或插件可能使用不同的 webpack 副本,不能只检查本机全局命令;保存原包清单和锁文件,核对实际执行构建的依赖树,再从原入口重新生成整份输出。

不建议手改 @jest/expect-utils 发布文件里的函数名。它可以成为定位差异的证据,却会在重装后丢失,也可能漏掉其他同类依赖。

直接配置 externals 也不能机械解决浏览器测试。排除依赖之后,浏览器仍需要用匹配的方式取得那个依赖;裸写一个包名不会自动在页面创建全局对象。若团队本来就有外部加载协议,应按该协议单独验收,否则容易从模块表错误变成语法错误或缺失依赖。

检查真实测试入口,不只看构建退出码

问题暴露在产物运行时,重新打包成功还不够。浏览器测试应执行真正调用 equals 等函数的断言;扩展则需要检查原激活路径。更新后对照产物里的嵌套 require 绑定,确认模块 ID 由正确的模块表解析。

同时检查生产压缩与开发构建,避免只保留一份通过的旧缓存。若仍有相同错误,记录新的 ID、模块文件和调用栈,继续排查产物缺失、构建混用或其他依赖转换,不能因版本已更新就忽略实际运行结果。