Rollup+Esbuild打包ESM产物出现require静态提取警告如何解决?
问题描述
我在使用rollup和esbuild将基于Typescript开发的npm包打包为目标ES2015的esm格式产物时遇到了异常问题。
tsconfig.json配置如下:
{ "extends": "../tsconfig.default.json", "compilerOptions": { "target": "esnext", "outDir": "dist", "rootDir": "src" }, "include": [ "./src/**/*" // 仅包含src目录下内容,dist、测试文件等自动排除 ] }
打包后的几乎所有esm产物头部都会自动插入一段require是否未定义的检查代码,我在未打包的源代码中完全没有使用过require,而且esm规范本身也不支持require。自动插入的代码如下:
// Added require check typeof require !== "undefined" ? require : (x) => { throw new Error('Dynamic require of "' + x + '" is not supported'); };
这段代码本身没有太大问题,但所有引入该npm包的React应用都会抛出上百条警告,提示require使用方式不正确,警告信息如下:
// Warning Message Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
疑问
请问这段自动插入的require检查代码是什么原因导致生成的?该如何移除这段代码避免警告?
注:我已经查阅过Angular相关的同警告问题帖,不适用于当前场景。
解决方案
触发原因
这段代码是esbuild自动插入的跨模块格式兼容逻辑,触发条件为以下任意一种:
- 你的源码或依赖的第三方npm包中存在动态
require调用(即参数为变量的require()写法),esbuild为了让产物能同时兼容CommonJS和ESM运行环境,会自动补上这段兜底逻辑 - 打包配置中没有显式指定输出纯ESM格式,esbuild默认会做兼容处理,自动插入该代码段
修复步骤
按优先级依次尝试以下调整即可:
- 调整esbuild配置,显式添加
platform: 'neutral'和format: 'esm'参数,明确告知esbuild输出纯ESM产物,不需要做CommonJS兼容处理 - 检查tsconfig配置,确认
compilerOptions.module设置为ESNext,moduleResolution设置为bundler,避免tsc将ESM导入语法转译为CommonJS的require调用 - 排查所有依赖的第三方包,若某个CommonJS格式的依赖存在动态
require逻辑,可在rollup配置中将该包加入external外置列表,避免esbuild处理该依赖的兼容逻辑 - 若上述方法都不生效,可在rollup插件链末尾添加替换插件,直接移除产物中的该段代码,参考配置如下:
import replace from '@rollup/plugin-replace'; export default { // 保留原有其他配置 plugins: [ // 保留原有其他插件 replace({ values: { 'typeof require !== "undefined" ? require : (x) => {\n throw new Error(\'Dynamic require of "\' + x + \'" is not supported\');\n};': '' }, delimiters: ['', ''], preventAssignment: true }) ] }
内容的提问来源于stack exchange,提问作者BennoDev
相关产品推荐
相关产品推荐

