package.json中"type": "module"是node.js模块解析的关键开关:设为"module"则所有.js文件按esm解析(禁用require),删除该字段即恢复commonjs行为(支持require、__dirname等);"type": "commonjs"无效,.mjs/.cjs后缀优先级高于type字段。

直接改 package.json 里的 "type" 字段就能切回 CommonJS,这是最简单也最可靠的方案。其他“加配置”“装插件”“改 launch.json”的做法,多数是治标不治本,甚至会引入新问题。
为什么 package.json 的 "type": "module" 是关键开关
Node.js 从 v12.20+ 开始,只要项目根目录存在 package.json 且含 "type": "module",所有 .js 文件默认按 ES Module 解析——这时 require()、__dirname、module.exports 全部失效,报错如 Error [ERR_REQUIRE_ESM] 或 ReferenceError: __dirname is not defined。
- 删掉这一行,Node 就恢复传统 CommonJS 行为:支持
require()、exports、__dirname、__filename - 如果项目没有
package.json,新建一个空文件即可(内容可为{}),Node 默认按 CommonJS 处理 - 注意:
"type": "commonjs"是无效写法,Node 不识别,只认"module"或不设该字段
require() 加载 .mjs 文件时报 ERR_REQUIRE_ESM 怎么办
这不是 VSCode 的问题,而是 Node 模块加载器的硬性限制:CommonJS 的 require() 绝对不能加载 ESM 格式文件(哪怕内容只是 export const x = 1)。
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
- 别试图用
node --loader或改文件后缀糊弄,VSCode 的终端或 Code Runner 插件仍会走原生require()路径 - 若必须调用 ESM 模块,改用动态
import():const mod = await import('./utils.mjs');(注意:需在 async 函数内) - 若需同步加载(比如 CLI 初始化),用
createRequire构造专用加载器:import { createRequire } from 'module'; const require = createRequire(import.meta.url);,但只能加载.cjs或未被"type": "module"影响的.js
VSCode “运行代码”插件(如 Code Runner)默认行为陷阱
这类插件通常直接执行 node xxx.js,完全不读 package.json 的 "type" 字段,也不管你有没有配置 launch.json。它只看文件扩展名和当前 Node 版本默认规则。
- 如果你的
index.js里写了export default,但package.json没设"type": "module",Code Runner 仍可能因 Node 版本高而报Unexpected token 'export' - 最稳解法:卸载 Code Runner,改用 VSCode 内置调试器(
launch.json配"runtimeExecutable": "node"),它会尊重package.json的模块类型声明 - 或者,在 VSCode 终端手动运行
node index.js——只要package.json正确,结果一定和内置调试器一致
CommonJS 和 ESM 的边界不在编辑器,而在 Node 的模块解析逻辑。VSCode 只是执行环境的入口,真正起作用的是 package.json + Node 版本 + 文件后缀三者组合。改错一个地方,整个链路就断了。










