Node 的 Typescript 库作为 NPM 中的混合包

Ati*_*ris 6 commonjs node.js npm typescript ecmascript-6

如何正确配置typescript tsconfig.jsonnpm package.json以创建混合 npm 包

我主要遵循这篇文章(但我也尝试过其他方法)

这是我的库gomshal 在 github 上的alpha 版本。我在这里描述的最后一个状态是在分支 Hybrid-2.3中。我想使用ESM 作为基本导入,并使用CommonJS 作为选项。这在本文的 2.3 章中进行了描述。我的 lib 文件通过Gomshal 类、枚举和接口导出。index.ts

项目结构

我的来源在"./src/lib". 我有两个 tsconfig.json 文件:tsconfig.esm.jsontsconfig.cjs.json。两者都包含相同的"./src/lib/**/*.ts"文件作为源。不同之处在于编译器选项:

// tsconfig.cjs.json for CommonJS
"compilerOptions": {
  "outDir": "./build/lib/cjs",
  "target": "ES5",
  "module": "CommonJS",
  ...
}

// tsconfig.esm.json for ES6 module
"compilerOptions": {
    "outDir": "./build/lib/esm",
    "target": "ES2015",
    "module": "ES2015",
  ...
}
Run Code Online (Sandbox Code Playgroud)

此外,我还有一个package.json特定于 commonjs 的文件,其内容为:{ "type": "commonjs" }。我的根 package.json 中的重要键是:

{
  "type": "module",
  "main": "./build/lib/esm/index.js",
  "module": "./build/lib/esm/index.js",
  "typings": "./build/lib/esm/index.d.ts",
  "files": [ "build/lib/**/*" ],
  "exports": {
    "./esm": "./build/lib/esm/index.js",
    "./cjs": "./build/lib/cjs/index.js"
  },
  ...
}
Run Code Online (Sandbox Code Playgroud)

所以这里的一切默认都是针对ES6 模块的。编译后(tsc -p tsconfig.esm.jsontsc -p tsconfig.cjs.json)会在构建目录中创建两个文件夹(build/lib/cjsbuild/lib/esm)。包 json 文件被src/cjs复制到build/lib/cjs,一切看起来都准备好发布了。现在,当我尝试npm pack使用此设置时,将生成的 tgz 文件复制npm install到演示项目(package.json:的一部分"type": "module", "dependencies": {"gomshal": "file:gomshal-1.4.2.tgz"}),最小演示index.js

// tsconfig.cjs.json for CommonJS
"compilerOptions": {
  "outDir": "./build/lib/cjs",
  "target": "ES5",
  "module": "CommonJS",
  ...
}

// tsconfig.esm.json for ES6 module
"compilerOptions": {
    "outDir": "./build/lib/esm",
    "target": "ES2015",
    "module": "ES2015",
  ...
}
Run Code Online (Sandbox Code Playgroud)

返回错误 ERR_MODULE_NOT_FOUND:

node .\index.js
(node:23404) ExperimentalWarning: The ESM module loader is experimental.
internal/modules/esm/resolve.js:58
  let url = moduleWrapResolve(specifier, parentURL);
            ^

Error: Cannot find module D:\Workspace\gomshal\npmtest\node_modules\gomshal\build\lib\esm\gomshal imported from D:\Workspace\gomshal\npmtest\node_modules\gomshal\build\lib\esm\index.js
    at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:58:13)
    at Loader.resolve (internal/modules/esm/loader.js:85:40)
    at Loader.getModuleJob (internal/modules/esm/loader.js:188:40)
    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:42:40)
    at link (internal/modules/esm/module_job.js:41:36) {
  code: 'ERR_MODULE_NOT_FOUND'
Run Code Online (Sandbox Code Playgroud)

我尝试了 root package.json 中的其他变体("main"针对 cjs 并"module"针对 esm 编译代码和其他键组合"exports"),但在这种情况下,我可能最接近混合包。我的节点版本是13.8.0,npm 6.13.6,tsc版本3.8.3。

但是,我仍然无法配置我的 npm 包以使命名的 ESM 导入import { Gomshal } from 'gomshal';可以无错误地使用。我错过了什么?