提供满足 esm、commonjs 和 bundlers 的 module、main 和 browser 字段
provide module, main and browser fields that satisfy esm, commonjs and bundlers
我有许多已发布的 npm 包,我已经升级它们以提供 commonjs 和 esm 构建。一些包可能同时适用于节点和浏览器。所有使用 webpack 或 rollup 编译的包。所有都是用打字稿写的,并转译到 dist
目录中。
我创建了一个如下所示的 commonjs index.js
文件:
'use strict'
if (process.env.NODE_ENV === 'production') {
module.exports = require('./react-abortable-fetch.cjs.production.min.js')
} else {
module.exports = require('./react-abortable-fetch.cjs.development.js')
}
我将 package.json main
字段设置为上面的 index.js
文件。
我还为每个包生成一个 .esm.js
文件,我将 browser
和 module
字段都设置为 esm.js
文件并设置 type
文件为 module
.
最终结果是这样的:
"type": "module",
"main": "dist/index.js",
"browser": "dist/react-abortable-fetch.esm.js",
"module": "dist/react-abortable-fetch.esm.js",
"types": "dist/index.d.ts",
这种方法的问题是只有 esm 包可以使用它(除非我错了)。
配置 package.json
文件的最佳方法是什么,以便尚未实现飞跃的包(而且相当多)仍然可以使用该包?
想法是利用 Node.js conditional exports 根据导入模块的方式自定义导入行为(require
或 import
)。
为了让 CommonJS 和 ESM 有两个不同的接口,您可以:
- 转译为 CommonJS 和 ESM(允许在同一个应用程序中为您的库意外使用
import
和 require
,这可能会导致不需要的和不可预测的行为)
- 将实现作为 ESM 和 CommonJS 包装器(不可能,因为当它具有顶级
await
时你不能 require
ECMAScript 模块)
- 将实现作为 CommonJS 和 ESM 包装器(最佳实际解决方案)
因此您必须将 CommonJS 设置为 TypeScript 转译目标,然后创建一个 ESM 包装器(最好在专用文件夹中)。最后将CommonJS和ESM入口点映射到package.json
:
中对应的文件
"exports": {
"require": "./index.js",
"import": "./esm/index.js"
}
我在这里发布了一个最小的工作项目:https://github.com/Guerric-P/demo-commonjs-esm
为了使用 TypeScript 中的库,每个 JavaScript 个文件还需要一个 .d.ts
文件。
我有许多已发布的 npm 包,我已经升级它们以提供 commonjs 和 esm 构建。一些包可能同时适用于节点和浏览器。所有使用 webpack 或 rollup 编译的包。所有都是用打字稿写的,并转译到 dist
目录中。
我创建了一个如下所示的 commonjs index.js
文件:
'use strict'
if (process.env.NODE_ENV === 'production') {
module.exports = require('./react-abortable-fetch.cjs.production.min.js')
} else {
module.exports = require('./react-abortable-fetch.cjs.development.js')
}
我将 package.json main
字段设置为上面的 index.js
文件。
我还为每个包生成一个 .esm.js
文件,我将 browser
和 module
字段都设置为 esm.js
文件并设置 type
文件为 module
.
最终结果是这样的:
"type": "module",
"main": "dist/index.js",
"browser": "dist/react-abortable-fetch.esm.js",
"module": "dist/react-abortable-fetch.esm.js",
"types": "dist/index.d.ts",
这种方法的问题是只有 esm 包可以使用它(除非我错了)。
配置 package.json
文件的最佳方法是什么,以便尚未实现飞跃的包(而且相当多)仍然可以使用该包?
想法是利用 Node.js conditional exports 根据导入模块的方式自定义导入行为(require
或 import
)。
为了让 CommonJS 和 ESM 有两个不同的接口,您可以:
- 转译为 CommonJS 和 ESM(允许在同一个应用程序中为您的库意外使用
import
和require
,这可能会导致不需要的和不可预测的行为) - 将实现作为 ESM 和 CommonJS 包装器(不可能,因为当它具有顶级
await
时你不能require
ECMAScript 模块) - 将实现作为 CommonJS 和 ESM 包装器(最佳实际解决方案)
因此您必须将 CommonJS 设置为 TypeScript 转译目标,然后创建一个 ESM 包装器(最好在专用文件夹中)。最后将CommonJS和ESM入口点映射到package.json
:
"exports": {
"require": "./index.js",
"import": "./esm/index.js"
}
我在这里发布了一个最小的工作项目:https://github.com/Guerric-P/demo-commonjs-esm
为了使用 TypeScript 中的库,每个 JavaScript 个文件还需要一个 .d.ts
文件。