纯 esm 包中无法使用 require() 是 node.js 的设计约束而非兼容性问题,必须用 import 替代,优先选用原生 esm 依赖,必要时用 import() 动态加载 commonjs 模块。

纯 ESM 包(即 "type": "module" 的包)中无法使用 require(),这是 Node.js 的强制限制,不是兼容性“问题”,而是设计约束。解决思路不是绕过限制,而是用 ESM 原生方式替代 CommonJS 模式。
用 import 替代 require 是根本方案
所有依赖必须支持 ESM 才能直接 import。优先选择已提供原生 ESM 的包(如 lodash-es、picocolors),或确认其 package.json 中有 "exports" 字段且包含 "import" 条目。
- ✅ 正确写法:
import { debounce } from 'lodash-es'; - ❌ 禁止写法:
const { debounce } = require('lodash');(运行时报错require is not defined) - 若依赖只有 CommonJS 版本(如旧版
chalk),需检查它是否通过"exports"或"main"+"type": "commonjs"提供 ESM 兼容入口;现代版本通常已支持
动态 import() 加载 CommonJS 模块(有限适用)
Node.js 允许在 ESM 中用 import() 动态导入 CommonJS 模块,返回的默认导出是整个 module.exports 对象。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 适用于按需加载、插件系统或遗留模块集成场景
- 示例:
const chalk = await import('chalk');→ 使用chalk.default.red('text')(注意.default) - 不推荐用于高频/顶层静态导入,破坏 tree-shaking 且语义不清晰
避免混合模块类型陷阱
纯 ESM 包中,所有本地文件也必须是 ESM(以 .mjs 结尾,或 .js 文件配合 "type": "module")。不能混用 require('./foo.js') 即使该文件是 CommonJS。
- 迁移本地代码:把
module.exports = ...改为export default ...或具名export const ... - 若必须保留 CommonJS 文件(如第三方脚本),可改用
import()动态加载,而非require - 构建工具(如 Vite、esbuild)通常自动处理,但纯 Node.js 运行时下必须严格遵守规则
借助工具桥接(仅开发/过渡期)
极少数情况下,若强依赖大量未升级的 CommonJS 包,可考虑:
- 用
createRequire(Node.js 内置)在 ESM 文件中创建一个require函数,但只能用于加载 CommonJS 模块,且不推荐用于生产环境 - 示例:
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url); const pkg = require('./legacy.cjs'); - 这不是“兼容”,而是降级使用;长期应推动依赖升级或自行封装 ESM wrapper
不复杂但容易忽略:ESM 和 CommonJS 是两种不兼容的模块系统,纯 ESM 环境下 require 是被移除的 API,不是 bug。关键在选对生态、改写导入方式、理解动态 import 行为。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










