也就是说imports只对当前包内的文件生效,而exports 可以根据 其他人如何导入我的包内的文件生效
对,准确说是这样
imports 和 exports 的作用域不一样,而且语义也不一样。
imports
它是"当前包内部"的解析规则。
也就是在这个包里,代码写:
js
import x from '#/foo'
时,Node/Vite 会在"当前 package"的上下文里查 package.json#imports,并把它映射成真正的文件路径。
它不关心"别人怎么从外部 import 你的包";它关心的是:
- 这个包内部的源代码
- 当前模块如何解析
#开头的 specifier
所以它只对当前包内的模块生效。
exports
它是"对外发布接口"的规则。
比如你在包里配置:
json
{
"name": "my-lib",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"./foo": {
"import": "./dist/foo.mjs",
"require": "./dist/foo.cjs"
}
}
}
这种配置决定的是:
- 外部代码怎么从你的包里 import
- 允许哪些入口暴露出来
- 根据
import/require/node/browser等条件返回不同文件
也就是说,exports 控制的是:
- 别人如何导入我这个包
- 这个包对外暴露哪些文件
- 入口如何按环境区分 ESM / CJS
一句话区分
imports:当前包自己内部用exports:别人外部使用这个包时用
举个例子
你的包内
json
{
"imports": {
"#/*": "./src/*"
}
}
在这个包内部写:
ts
import a from '#/utils/a'
能用。
但外部项目:
js
import myLib from 'your-package'
不会去读这个 imports。
你的包对外
json
{
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
}
}
外部项目再用:
js
import myLib from 'your-package'
或者
js
const myLib = require('your-package')
就会按条件走不同入口。
所以你的理解是对的
imports只对当前包内的文件生效;
exports影响的是其他人如何导入这个包里的内容。
这两个字段是不同层面的规则,别混在一起。
如果你愿意,我可以再补一个"imports / exports / resolve.alias / tsconfig.paths"的四者对照图,最容易记住。