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

如何将ESM模块的import转译为CommonJS?Babel转译失败求助

问题背景

我正在开发一个必须为CommonJS格式的包,因为使用它的项目暂不支持import/export语法。我的包依赖仅支持ESM的模块globby。

原本打算用Babel转译所有代码,期望Babel能将import转换为可正常运行的动态import()形式,但方案无效。项目调用我的包时抛出错误:

Error [ERR_REQUIRE_ESM]: require() of ES Module /mydir/project/node_modules/globby/index.js
from /mydir/project/node_modules/mypackage/index.js not supported.
Instead change the require of index.js in
/mydir/project/node_modules/mypackage
to a dynamic import() which is available in all CommonJS modules.

我原本期望Babel能将

import {globby} from 'globby'

转换为CommonJS可使用的形式,但并未实现。使用的Babel版本为7.19,babel.config.js配置如下:

module.exports = api => {
  api.cache(true)
  const presets = [['@babel/preset-env',
    {
      "loose": true,
      "targets": { "node": 16 },
      "modules": 'commonjs'
    }
  ]]
  const ignore = ['./src/tooltip.js']
  const plugins = ["@babel/plugin-syntax-dynamic-import",
    ["@babel/plugin-transform-modules-commonjs", {
      "allowTopLevelThis": true
    }]]
  return { presets, ignore, plugins }
}
解决方案

1. 明确Babel的转换边界

Babel只会转换你的业务代码中的模块语法,不会修改第三方依赖的代码结构。globby本身是ESM模块,转译后你的代码仍会尝试用require()加载它,这就是报错的核心原因。

2. 手动改用动态import()加载globby

CommonJS模块原生支持动态import()(返回Promise),直接在代码里替换静态import:

// 异步函数内使用
async function scanFiles() {
  const { globby } = await import('globby');
  const result = await globby(['src/**/*.js']);
  return result;
}

如果需要在模块顶层初始化,可以用立即执行异步函数:

let globbyInstance;
(async () => {
  const module = await import('globby');
  globbyInstance = module.globby;
})();

// 后续使用时确保实例已初始化
async function useGlobby() {
  if (!globbyInstance) throw new Error('globby未完成初始化');
  return await globbyInstance(['*.json']);
}

3. 简化Babel配置避免冲突

@babel/preset-env已经内置了@babel/plugin-transform-modules-commonjs的功能,无需单独在plugins中重复配置,否则可能导致转换逻辑冲突。调整后的配置如下:

module.exports = api => {
  api.cache(true)
  const presets = [['@babel/preset-env',
    {
      "loose": true,
      "targets": { "node": 16 },
      "modules": 'commonjs'
    }
  ]]
  const ignore = ['./src/tooltip.js']
  const plugins = ["@babel/plugin-syntax-dynamic-import"];
  return { presets, ignore, plugins }
}

4. 备选方案:寻找globby的CJS兼容版本

部分ESM包会同时提供CommonJS格式的入口,可检查globby的文档或package.json确认是否有对应版本。如果没有,不推荐额外引入esm加载器,这会增加使用方的配置成本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 12:45:30