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

如何让npm包stack-player同时支持ES Modules与CommonJS

让ES Modules包兼容CommonJS的低成本方案(无需全项目转换)

不用把整个老项目改成ES Modules,这两个方案就能让你的stack-player同时支持import和require导入:

方案一:双入口配置(推荐)

通过打包工具生成CommonJS版本的代码,原ESM代码完全保留,不用修改。

  1. 生成CJS版本代码
    用轻量的打包工具(比如esbuild或Rollup)把你的ESM源码打包成CommonJS格式。以esbuild为例,执行命令:
# 安装esbuild(可选全局安装)
npm install esbuild --save-dev
# 打包生成CJS版本到cjs目录
esbuild src/index.js --bundle --format=cjs --outfile=cjs/index.js

如果你的包有多个子模块,需要对应打包每个文件,或者配置esbuild的入口列表。

  1. 修改package.json配置
    在package.json里添加条件导出规则,明确指定不同导入方式对应的入口文件:
{
  "name": "stack-player",
  "type": "module", // 声明原项目是ESM
  "main": "./cjs/index.js", // 兼容旧版Node.js的require入口
  "module": "./src/index.js", // ESM入口
  "exports": {
    ".": {
      "require": "./cjs/index.js",
      "import": "./src/index.js"
    }
    // 如果有子模块,继续添加对应配置
    // "./utils": {
    //   "require": "./cjs/utils.js",
    //   "import": "./src/utils.js"
    // }
  }
}

exports字段是Node.js 12+支持的条件导出,优先级高于main和module,能精准匹配不同的导入方式。

  1. 测试验证
  • 在CommonJS项目中测试:
const stackPlayer = require('stack-player');
console.log(stackPlayer); // 正常输出模块内容
  • 在ESM项目中测试:
import stackPlayer from 'stack-player';
console.log(stackPlayer); // 正常输出模块内容

方案二:CommonJS适配文件(无需打包)

如果不想用打包工具,可以新增一个CommonJS入口文件,通过动态import适配ESM模块,但注意这种方式返回的是Promise,需要用户异步使用:

  1. 新建index.cjs文件
    在包根目录创建index.cjs,内容如下:
// 动态导入ESM模块
async function loadStackPlayer() {
  const { default: stackPlayer } = await import('./src/index.js');
  return stackPlayer;
}

// 导出Promise,用户需要await获取模块
module.exports = loadStackPlayer();
  1. 修改package.json
{
  "name": "stack-player",
  "type": "module",
  "main": "./index.cjs",
  "module": "./src/index.js",
  "exports": {
    ".": {
      "require": "./index.cjs",
      "import": "./src/index.js"
    }
  }
}
  1. 用户使用方式
    CommonJS项目中需要异步获取:
// CommonJS项目
require('stack-player').then(stackPlayer => {
  // 使用stackPlayer
});

// 或者用async/await
async function init() {
  const stackPlayer = await require('stack-player');
  // 使用stackPlayer
}
init();

这个方案的缺点是CommonJS用户需要异步处理,体验不如方案一,所以更推荐方案一。

注意事项

  • 确保打包后的CJS代码没有语法错误,比如ESM的import/export已经被转成require/module.exports
  • 如果你的包依赖其他ESM包,打包工具会自动处理依赖的转译,不用担心兼容性
  • 发布前记得把cjs目录(或打包生成的文件)加入package.json的files字段,确保发布到npm时包含这些文件:
"files": [
  "src",
  "cjs"
]

内容的提问来源于stack exchange,提问作者Islam Y-

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 17:05:28