如何让npm包stack-player同时支持ES Modules与CommonJS
让ES Modules包兼容CommonJS的低成本方案(无需全项目转换)
不用把整个老项目改成ES Modules,这两个方案就能让你的stack-player同时支持import和require导入:
方案一:双入口配置(推荐)
通过打包工具生成CommonJS版本的代码,原ESM代码完全保留,不用修改。
- 生成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的入口列表。
- 修改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,能精准匹配不同的导入方式。
- 测试验证
- 在CommonJS项目中测试:
const stackPlayer = require('stack-player'); console.log(stackPlayer); // 正常输出模块内容
- 在ESM项目中测试:
import stackPlayer from 'stack-player'; console.log(stackPlayer); // 正常输出模块内容
方案二:CommonJS适配文件(无需打包)
如果不想用打包工具,可以新增一个CommonJS入口文件,通过动态import适配ESM模块,但注意这种方式返回的是Promise,需要用户异步使用:
- 新建index.cjs文件
在包根目录创建index.cjs,内容如下:
// 动态导入ESM模块 async function loadStackPlayer() { const { default: stackPlayer } = await import('./src/index.js'); return stackPlayer; } // 导出Promise,用户需要await获取模块 module.exports = loadStackPlayer();
- 修改package.json
{ "name": "stack-player", "type": "module", "main": "./index.cjs", "module": "./src/index.js", "exports": { ".": { "require": "./index.cjs", "import": "./src/index.js" } } }
- 用户使用方式
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-
相关产品推荐
相关产品推荐

