exports条件导出与TS支持
exports字段精确控制包的公开API和条件导出,types字段为TypeScript提供类型支持。
exports条件导出
基本语法
JSON
{
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"./utils": {
"import": "./dist/utils.mjs",
"require": "./dist/utils.cjs"
}
}
}
".":包主入口,等价于main"./utils":子路径导出,允许import { x } from 'my-lib/utils'
条件匹配优先级
Node.js从上到下匹配第一个符合条件的入口:
JSON
{
"exports": {
".": {
"node": "./dist/index.node.js",
"default": "./dist/index.js"
}
}
}
常见条件:
| 条件 | 匹配场景 |
|---|---|
| import | ESM的import加载 |
| require | CJS的require加载 |
| node | Node.js环境 |
| browser | 浏览器环境 |
| default | 兜底条件 |
封装性
exports定义了包的公开API,未列出的路径无法被导入:
JSON
{
"exports": {
".": "./dist/index.js",
"./utils": "./dist/utils.js"
}
}
JavaScript
// 成功
import pkg from 'my-lib';
import { helpers } from 'my-lib/utils';
// 报错:PACKAGE_PATH_NOT_EXPORTED
import secret from 'my-lib/internal';
启用exports后,包内未导出的路径完全不可访问,这是与main的本质区别。
types字段TypeScript支持
独立types字段
JSON
{
"name": "my-lib",
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts"
}
types(或typings)指定类型定义文件入口。
exports中内联types条件
JSON
{
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"./utils": {
"types": "./dist/utils.d.ts",
"import": "./dist/utils.mjs",
"require": "./dist/utils.cjs"
}
}
}
types条件必须放在最前面。TypeScript按条件列表顺序匹配,如果import先匹配到,将跳过types条件导致类型丢失。
TypeScript的moduleResolution
JSON
// tsconfig.json
{
"compilerOptions": {
"moduleResolution": "bundler"
}
}
node10:仅识别main和typesbundler/nodenext:识别exports中的条件导出
使用exports条件导出时,tsconfig的moduleResolution应设为bundler或nodenext,否则TypeScript无法解析条件导出路径。
要点总结
- exports精确控制包的公开API,未导出路径不可访问
- 条件导出为import/require/node/browser提供不同入口
- exports中types条件必须放在最前面,否则TypeScript无法识别
- moduleResolution设为bundler或nodenext才支持exports解析
- exports替代main/module/browser的碎片化方案,是现代包的标准配置