es模块中无法使用require,因node.js为esm和commonjs维护独立加载器,require仅存在于commonjs作用域;应优先用import或await import,必要时通过createrequire调用commonjs模块。

因为 ES 模块(type="module")和 CommonJS 是两种互不兼容的模块系统,底层机制完全不同,Node.js 在解析 type="module" 文件时根本不会提供 require 函数。
模块加载机制天生隔离
ES 模块采用静态分析、提前编译、单例缓存、顶层 await 支持等特性;CommonJS 则依赖动态执行、运行时求值、每次 require 都可能返回新实例。Node.js 为两者维护完全独立的加载器(esm loader 和 cjs loader),彼此不共享全局变量或 API —— require 只存在于 CommonJS 环境的模块作用域中,在 ESM 脚本里它根本未被定义。
语法与语义不可混用
import 必须写在顶层、不能条件导入、不支持表达式路径;而 require() 是函数调用,可出现在任意位置、支持拼接路径、可被 try/catch 包裹。这两种行为无法在同一个模块系统中统一。即使你用 Babel 或 Webpack 把 import 编译成 require,只要最终产物被 Node.js 当作 ESM 执行(比如文件后缀是 .mjs、或 package.json 中有 "type": "module"),运行时仍会报错:ReferenceError: require is not defined。
Node.js 明确禁止跨系统调用
从 v12 开始,Node.js 对 ESM 的实现严格遵循 ECMAScript 规范。规范要求 ESM 模块不能访问 CommonJS 的上下文对象(如 module、exports、require)。即便通过 createRequire 临时获取一个 require 实例,也只能用于加载 CommonJS 模块,且必须传入一个 CommonJS 文件路径 —— 它不能在 ESM 模块内部替代原生 import,也不能用于加载另一个 ESM 文件。
替代方案不是绕过限制,而是适配体系
- 用
import替代require:这是标准做法,所有现代库都提供 ESM 入口(查看package.json中的exports或module字段) - 需要动态导入时,统一使用
await import('...'),它在 ESM 和 CommonJS 中都合法 - 若必须调用 CommonJS 模块,确保目标包同时发布 ESM 兼容版本,并通过命名导入(
import { foo } from 'pkg')而非require - 混合项目中,可通过
createRequire(import.meta.url)在 ESM 文件内安全调用 CommonJS 模块,但仅限于明确需兼容旧包的场景











