如何将TypeScript ESM模块发布为NPM包?
关于将CommonJS NPM包转为ESM的问题解答
问题1:dist/index.js和dist/index.d.ts应如何编写?是否直接复制lib中的对应文件即可?
原项目的dist目录采用了冗余的“自依赖转发”模式(dist/package.json依赖自身),这种设计完全没必要,建议直接简化:
- 如果你想保留dist作为发布目录,直接将lib目录下编译好的
index.js、index.d.ts复制到dist目录即可,同时删除dist/package.json中指向自身的依赖项("@username/my-package": "3.0.0"),避免循环依赖问题。 - 更合理的方案是调整
tsconfig.json,将outDir直接设为dist,这样TypeScript编译后直接输出到dist,不需要维护lib和dist两个目录,彻底消除转发冗余。
如果坚持保留原转发结构,dist/index.js需要改为ESM语法:
export { toc, default, CssClasses, Options } from '../lib/index.js';
对应的dist/index.d.ts改为:
export { toc, default, CssClasses, Options } from '../lib/index.js';
问题2:要使包完全转为ESM,src/index.ts和dist/index.js中的module.exports代码应替换为什么?
src/index.ts
原代码中的CommonJS兼容代码(if (typeof module === "object"...))可以直接删除,因为纯ESM包不需要兼容CommonJS的module.exports逻辑。同时注意原代码中import { toc } from "./my-package"是错误路径,应该从核心逻辑文件./toc导入,修改后的src/index.ts如下:
export { CssClasses, Options } from "./options"; export * from "./types"; export { toc } from "./toc"; export default toc;
dist/index.js
如果保留dist转发结构,需要将原CommonJS的module.exports改为ESM导出语法,示例如下:
export { toc, default, CssClasses, Options } from '../lib/index.js';
如果直接将lib的文件复制到dist,则不需要额外修改,直接使用编译后的ESM代码即可。
问题3:除了添加"type": "module"外,dist/package.json还需配置哪些内容?发布真的只需要dist中的3个文件吗?
额外配置项
- 删除无效依赖:必须删掉dist/package.json中
"dependencies"里的"@username/my-package": "3.0.0",这是循环依赖,完全无效。 - 明确入口与类型:保留
"main": "index.js"的同时,建议添加"module": "index.js"(虽然ESM环境下main已生效,但该字段能让工具更明确识别包的模块类型),确保"types": "index.d.ts"指向正确的类型文件。 - 调整Node版本要求:将
"engines.node"设为>=14.13.0(Node.js 14.13.0才正式支持"type": "module")或更高版本,避免低版本Node用户安装后报错。 - 完善files字段:如果你的包只有入口文件和类型文件,
"files": ["index.js", "index.d.ts"]足够;但如果包依赖其他编译后的模块文件(比如options.js、types.d.ts等),需要将这些文件也添加到files数组中,否则用户导入时会找不到模块。
发布文件范围
不是只需要3个文件。如果你的包包含多个模块(比如src下的options.ts、types.ts等),这些文件编译后的JS和类型文件都需要包含在发布包里,否则用户使用时会出现模块找不到的错误。最稳妥的方式是将所有编译后的ESM文件和类型文件都纳入发布范围,或者直接将tsconfig的outDir设为dist,编译后发布整个dist目录。
内容的提问来源于stack exchange,提问作者matt
相关产品推荐
相关产品推荐

