You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node+TypeScript+oclif项目引入d3.js报ERR_REQUIRE_ESM如何解决

问题根因
  • d3 v7及以上版本是纯ESM包,完全不支持CommonJS规范的require()语法导入
  • 你当前用的oclif默认TS配置把编译模块规范设为commonjs,TS编译时会把所有ESM风格的静态import、甚至你手写的动态import()都降级转成require()调用,这就是为什么你照着报错提示改了动态导入还是失败——编译后的代码根本没保留动态import语法,跑的时候还是走require加载d3,必然报ERR_REQUIRE_ESM。
可落地解决方案

方案1:保留原有CommonJS配置,最小改动修复

适合不想大改现有项目结构的场景,只需要改两处:

  1. 调整tsconfig.json,新增配置项开启ESM兼容:
{
  "compilerOptions": {
    "declaration": true,
    "importHelpers": true,
    "module": "commonjs",
    "moduleResolution": "node",
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "target": "es2019",
    "esModuleInterop": true
  },
  "include": ["src/**/*"]
}
  1. 删掉文件顶部对d3的静态导入,把所有用到d3的逻辑放到async函数中,在函数内部用动态import加载d3:
// 删掉顶部的 import * as d3 from 'd3'
async function buildGraphTree() {
  // 注意这里要取default属性,d3是默认导出
  const d3 = (await import('d3')).default;
  // 后续正常写d3的业务逻辑即可,select、比例尺等方法都能正常调用
}
  1. 重新执行构建命令npm run build或者yarn build,再运行程序就不会报错。如果编译后发现dist里对应代码还是require,把tsconfig里的target改成es2020再重新编译就行。

方案2:全项目切换为ESM规范(长期维护推荐)

如果后续还要用其他纯ESM依赖,不想每次都写动态导入,可以直接把整个项目切到ESM,一劳永逸:

  1. 在package.json顶层加配置:"type": "module"
  2. 替换tsconfig.json里的模块相关配置:
{
  "compilerOptions": {
    "declaration": true,
    "importHelpers": true,
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "target": "es2020",
    "esModuleInterop": true
  },
  "include": ["src/**/*"]
}
  1. 把项目里所有相对路径的导入补全.js后缀,比如原来的import { parseTree } from './tree-util'要改成import { parseTree } from './tree-util.js'
  2. 调整oclif的启动脚本、eslint规则适配ESM规范,这个方案改动量稍大,但后续不会再遇到CommonJS和ESM的兼容问题。
注意事项
  • 别为了兼容去降级d3到v6及更早版本,旧版本存在未修复的安全漏洞,也不会再更新功能
  • 动态导入d3的时候一定要取.default,不然拿到的是整个模块命名空间对象,调用d3的方法会报“不是函数”的错
  • 改完配置一定要检查dist目录下的编译产物,确认加载d3的代码是原生import()语法而不是require(),不然配置改了也不生效。

内容的提问来源于stack exchange,提问作者DrKabum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 17:21:26