CommonJS项目导入ESM库遇ERR_REQUIRE_ESM错误,求解决方法
可以在CommonJS项目中导入ESM包吗?
可以,但不能使用常规的静态import或require(),因为Node.js会阻止CommonJS模块同步加载纯ESM包。以下是针对你的TypeScript CommonJS项目的可行解决方案:
方案1:使用动态import()(官方推荐)
Node.js允许所有CommonJS模块使用动态import()函数异步加载ESM包,这是最直接的解决方式。
具体实现
将原来的静态导入替换为异步动态导入,结合async/await处理:
// 替换静态导入:import { someFunc } from "esm-dependency"; async function initApp() { // 动态导入ESM依赖 const esmDependency = await import("esm-dependency"); // 注意:如果依赖使用默认导出,需要访问.default属性 const { someFunc } = esmDependency; // 后续业务逻辑,比如启动Express服务 const express = require("express"); const app = express(); app.get("/", (req, res) => { res.send(someFunc()); }); app.listen(3000, () => { console.log("Server running on port 3000"); }); } initApp();
TypeScript配置注意
确保tsconfig.json中以下配置正确:
{ "compilerOptions": { "module": "CommonJS", "target": "ES2017", // 需支持async/await特性 "moduleResolution": "Node10", "esModuleInterop": true, "allowSyntheticDefaultImports": true } }
方案2:转译ESM依赖为CommonJS
如果动态导入的异步逻辑对你的项目结构不友好,可以通过构建工具将ESM依赖转译为CommonJS格式后再导入。
用esbuild批量转译
编写简单脚本,用esbuild把ESM依赖打包成CommonJS:
// build-deps.js const esbuild = require('esbuild'); esbuild.build({ entryPoints: ['node_modules/esm-dependency/index.js'], outfile: 'dist/esm-dependency.cjs', format: 'cjs', bundle: true, }).catch(() => process.exit(1));
运行脚本后,直接导入转译后的文件:
const { someFunc } = require("./dist/esm-dependency.cjs");
注意事项
- 这种方式需要维护转译脚本,依赖更新后需重新转译
- 部分依赖可能包含无法转译的ESM特性,需测试验证
为什么你之前的方案没奏效?
- Webpack相关方案仅适用于Webpack打包的项目,如果你的项目是用
ts-node直接运行,该方案不适用 - Babel-loader方案需要正确配置
@babel/preset-env和@babel/plugin-syntax-dynamic-import,且需确保Babel处理了node_modules中的ESM依赖(默认Babel会忽略node_modules)
内容的提问来源于stack exchange,提问作者BSimpson
相关产品推荐
相关产品推荐

