err_require_esm 错误是因 commonjs 的 require() 被 node 硬性禁止加载 esm 模块(如 .mjs 或 type: "module" 下的 .js),解决核心是匹配执行环境与模块类型:改后缀为 .mjs、配 package.json 的 "type": "module" 并统一改 import、或在 cjs 中用动态 import() 加载 esm。

VSCode点“运行”就报 ERR_REQUIRE_ESM 怎么办
这是 VSCode 默认用 node script.js 执行文件,而该脚本或它 require() 的某个模块是 ESM(比如后缀为 .mjs,或依赖的包如 execa@8+、glob@10+ 已发布纯 ESM 版本),Node 直接拒绝加载——不是语法错,是模块加载器硬拦截。
解决思路不是“统一改成 ESM”,而是让执行环境匹配模块类型:
- 给文件改后缀:
script.js→script.mjs,VSCode 的 Code Runner 插件会自动识别并加--experimental-modules(Node v12+)或直接按 ESM 执行(v14+) - 在
package.json中加"type": "module",但必须同步把所有require()改成import,且不能再用__dirname、require.resolve等 CJS 特有变量 - 不改项目结构?那就别让 VSCode 直接跑
node xxx.js:右键 → “Open in Integrated Terminal”,手动执行node --loader ts-node/esm xxx.ts或node --input-type=module -e "import('./main.mjs')"
CommonJS 文件里怎么安全 import 一个 .mjs 模块
require('./utils.mjs') 必炸,但 Node 自 v12.17+ 就支持在 CJS 文件中用动态 import() 加载 ESM 模块——这是唯一被官方认可的跨规范调用方式。
注意三点:
-
import()返回 Promise,必须await或.then();不能写在顶层同步逻辑里(比如 CLI 参数解析需立即执行时) - 导入结果是命名空间对象:
const { foo } = await import('./utils.mjs'),不是默认导出直接解构 - 如果 ESM 模块用了
export default,得写成const { default: foo } = await import('./utils.mjs'),或者用const mod = await import('./utils.mjs'); const foo = mod.default
createRequire 能绕过 ERR_REQUIRE_ESM 吗
不能。它只解决“CJS 环境里想加载另一个 CJS 模块但 package.json 设了 "type": "module"”的问题,不是用来加载 .mjs 的。
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
典型误用场景:有人以为写了 const require = createRequire(import.meta.url) 就能 require('./utils.mjs') —— 实际仍会报错。
它的正确用途是:
- 在 ESM 文件(如
.mjs)里加载传统 CJS 模块:const config = require('./config.cjs') - 路径必须明确带后缀(
.cjs或.js),且目标文件不能含export/import语句 - 它生成的
require仍受 Node 模块系统规则约束:不支持.mjs、不支持 JSON 自动解析(需require('fs').readFileSync)
为什么改了 package.json 的 "type" 还是报错
因为 "type": "module" 只影响 .js 文件,不影响 .cjs 和 .mjs——它们各自按后缀强制解释。但很多人忽略了一个关键细节:子依赖的模块类型由它自己的 package.json 决定,不受你项目 "type" 控制。
常见陷阱:
- 你的
index.js是 ESM(因"type": "module"),但它import的第三方包(如lodash-es)内部又require()了某个 CJS 子模块,而那个子模块又试图import回来——形成混合加载链,Node 会卡在某一层报错 - VSCode 的调试器(
launch.json)没配runtimeArgs,比如没加--experimental-specifier-resolution=node,导致解析import 'pkg'时找不到入口 - 某些插件(如 ESLint、Prettier)读取配置文件时仍按旧模式解析,报
Unexpected token 'export',这不是运行时错误,得单独配parserOptions.project或关掉相关检查
最易被忽略的是:模块边界从来不在文件名,而在加载器链路。同一个 .js 文件,在 type: module 下是 ESM,在 type: commonjs 下是 CJS,而它引入的 .mjs 始终只能用 import(),.cjs 始终只能用 require() 或 createRequire。混用不是靠“兼容开关”,而是靠主动控制加载方式。










