webpack 5.110.3 打包后 require 变成连环调用:检查分号边界
无分号的相邻 require 在源码中合法,模块拼接后却变成函数调用链。核对 5.110.3 回归与正式修正,别修改第三方包来掩盖转换。
构建没有报错,加载 bundle 时却抛 __webpack_require__(...) is not a function,未压缩产物中出现 (a_namespaceFn())(b_namespaceFn())。若刚更新到 webpack 5.110.3,入口包含 ES import,依赖里又有不带分号的相邻 require,应检查模块拼接后的语句边界。
源码中的两条 require 本来就是合法的独立语句。问题来自 5.110.3 新生成的括号,使下一条表达式接到上一条返回值上;不需要 Electron,也不一定涉及未使用 re-export 被删除。
两行源码在产物里变成了一个调用
下面是结构示例,a、b、x 都是项目中的真实模块:
import X from './x.js';
window.X = X;
require('./a.js')
require('./b.js');
在受影响的拼接路径中,两条 require 被改写成带括号的引用。JavaScript 自动分号插入不会在前一表达式和下一行左括号之间强制断开,于是代码尝试调用 a 的导出,再把 b 的结果当参数;导出不是函数时便失败。
先保留未压缩产物,确认实际是这类连环调用。嵌套打包器把模块 ID 交给错误的模块表,也会出现“不是函数”,但那条问题不能靠分号边界解释。更换 Terser 版本也无法修正压缩之前已经形成的错误表达式。
更新构建器,短期处理要保留模块副作用
正式 webpack 5.111.0 已修正拼接后的 CommonJS 引用语句保护,当前 5.112.2 仍包含对应处理。按项目 loader、插件与运行环境的兼容要求采用包含修正的正式版,重新生成产物,避免把旧构建缓存当成更新结果。
如果触发语句在应用自己维护的源码中,明确加上分号可以作为局部过渡:
require('./a.js');
require('./b.js');
应保留两个模块原有加载顺序与副作用。问题出在第三方发布文件时,不宜批量重写 node_modules 中所有无分号代码;重装会丢掉改动,也可能漏掉其他入口。
必要时可按该版本的配置评估停用 CommonJS 拼接,例如 optimization.concatenateModules: { commonjs: false }。它改变优化策略及产物大小、结构,需要单独回归;不是关闭所有校验或删掉 require。采用正式修正后再决定是否撤回临时选项。
验收既看两个表达式在输出中已分开,也从真实入口加载 bundle,确认 a、b 都按预期执行。覆盖生产拼接和压缩构建,避免只在开发模式通过。对于原来有未使用 re-export 的依赖,还要保留该优化条件,确认删除赋值之后仍留下安全的语句边界。


