我在包根目录的 dist 文件夹中有为 ESM 和 CJS 格式构建的 NPM 包
package.json 中还有导出字段,例如:
{
"exports": {
"./foo": {
"types": "./dist/types/foo.d.ts",
"require": "./dist/cjs/foo.js",
"import": "./dist/esm/foo.js",
"default": "./dist/esm/foo.js"
},
"./bar": {
"types": "./dist/types/bar/index.d.ts",
"require": "./dist/cjs/bar/index.js",
"import": "./dist/esm/bar/index.js",
"default": "./dist/esm/bar/index.js"
},
"./hello/world": {
"types": "./dist/types/hello/world/index.d.ts",
"require": "./dist/cjs/hello/world/index.js",
"import": "./dist/esm/hello/world/index.js",
"default": "./dist/esm/hello/world/index.js"
}
}
}
如您所见,foo 是 foo.js 的别名,但 bar 是 bar/index.js 的别名
我在其他带有 TypeScript 的项目中使用这个包,tsc 看不到 bar 和 hello/world
它只看到 foo
import foo from 'my-pkg/foo' // WORKS FINE
import bar from 'my-pkg/bar'; // NOT WORKING (cannot find declarations for...)
import helloWorld from 'my-pkg/hello/world'; // NOT WORKING (cannot find declarations for...)
为什么会这样?
在没有 TypeScript 的 Node.js 中,它可以在 ESM 和 CJS 中正常工作,没有错误。
只有 TypeScript 找不到类型定义
这可能无法回答您的问题,但对于您想要完成的任务很重要,并且对于评论来说太长了。
这不会像你实现的那样工作,至少在我写这篇文章的时候不会。这很难做到,所以不要感到难过。现在我向你展示兔子洞有多深......
当您没有有
exports
地图节点时,将尊重您的package.json中的main
和module
条目,并会根据.js
文件是否为import
以正确的方式处理它们ed 或 require
d,只要您 不 将 type
设置为“模块”。
但是,一旦添加
exports
映射,它就会优先,并且 所有 .js 文件将被视为 CJS 或 ESM,具体取决于您在 package.json 中设置 type
的内容,无论它是否是 import
地图中的
require
或
exports
路径。所以这给了你三个选择:
exports
映射,将 type
设置为“commonjs”(或省略它)并使用 module
属性指向您的 ESM 入口点。选项#2和#3的问题是Typescript编译器不会为你添加它,并且他们一再拒绝实现这个。
值得注意的是,尽管规范规定 ESM 导入的扩展名应该是“.js”,但实际上几乎所有最新的工具(例如 Typescript、Rollup、Webpack、Vite)和最新的引擎(例如 V8、Webkit)将接受“.mjs”。
您可以使用 shell 脚本破解它,将文件扩展名替换为
find
/mv
和 sed
将文件扩展名附加到导入语句上,您可以通过使用真正的解析器来轻松完成此操作达到相同的结果,或者您可以使用像 this package 这样的东西来为您做到这一点。
如果您想查看这一切的实际效果,请参阅我在 GitHub 上写的 示例。
祝你好运!