如何将 package.json 导入 Typescript 文件而不将其包含在编译输出中?
Posted
技术标签:
【中文标题】如何将 package.json 导入 Typescript 文件而不将其包含在编译输出中?【英文标题】:How to import package.json into Typescript file without including it in the compiled output? 【发布时间】:2018-12-06 18:48:32 【问题描述】:使用 Typescript 2.9 我能够成功导入本地 package.json 文件并使用这些值。但是,当我只希望生成的 JS 文件使用实际的 package.json 时,我现在遇到了 package.json 文件包含在编译输出中的问题。
我的包有以下文件:
src/
index.ts
package.json
tsconfig.json
我的 index.ts 导入 package.json:
import pkg = require("../package.json");
我的 tsconfig.json 看起来像这样:
"compilerOptions":
"outDir": "./lib",
"module": "commonjs",
"resolveJsonModule": true,
"esModuleInterop": true
,
"include": [
"src/**/*"
]
理想的结果是:
lib/
index.js
package.json
但我实际得到的是:
lib/
src/
index.js
package.json
package.json
【问题讨论】:
接受的答案在写完一个月后就变成了不真实的。下面有两种可行的解决方案,应该接受其中一种。 【参考方案1】:当我只希望生成的 JS 文件使用实际的 package.json 时。
如果您的 src 文件的结构,您的 lib
将始终是一个直接副本。如果您将 package.json
包含到 TypeScript 编译上下文中,那么它会将您的库更改为 package.json + src
。
如何将 package.json 导入 Typescript 文件而不包含在编译输出中?
如果你导入它,你就不能。
另类
有 两个 项目,正如这个答案所提到的:https://***.com/a/61468012/390330
【讨论】:
该死的好吧,我认为可能是这种情况。对于其他对此感到困惑的人,我通过使用 fs 模块和JSON.parse()
手动引入 json 文件来解决它。
这个答案不正确(至少对于较新的 TypeScript 版本)。看看我下面的答案有解决办法。
@Dominik 这怎么不真实?你不能 import
它。您的解决方案使用require
。但是现在,即使是更新的代码,你的解决方案也行不通,因为每个人都在迁移到 ESM。
@Inigo 你是对的。我之所以这么说,是因为这个答案中的陈述“如果你导入它,你就不能”。而提问者在他们的问题中使用“要求”。我将“要求”视为一种导入方式(我仍然认为它在技术上是)。
@Dominik 明白了。需要注意的关键是,在这个答案中,baserat 将“import”一词斜体化......他强调了区别。【参考方案2】:
在tsconfig
中设置rootDir
选项,如下所示
"compilerOptions":
"rootDir": "./src"
`
【讨论】:
这真的没有意义。如果他想导入package.json,他会按照你说的去做。 TypeScript 会抱怨他正在尝试导入 rootDir 之外的文件,这完全有道理。【参考方案3】:?This approach won't work for ESM targets。如果您尝试创建 ES6 模块,则必须使用不同的解决方案。
我使用的是 TypeScript 3.5.1,如果我使用 require()
函数导入 package.json,那么它不会复制到编译输出,因此输出看起来像您的理想结果。
我的 tsconfig.json:
"compilerOptions":
"target": "es5",
"module": "commonjs",
"lib": ["es2015", "dom"],
"sourceMap": true,
"strict": true,
"moduleResolution": "node",
"downlevelIteration": true
"outDir": "./ts-out",
"noImplicitAny": false,
"suppressImplicitAnyIndexErrors": false
,
"include": [
"./src"
]
我只是这样导入它:
const pkg = require('../package.json');
我在 Facebook 的 Jest 框架源代码中找到了这个解决方案(他们使用的是 Lerna + TypeScript):https://github.com/facebook/jest/blob/master/packages/jest-core/src/version.ts
【讨论】:
如果你的目标模块系统是commonjs
,它就可以工作。但是,如果您的 module
是 ES6
/ESNext
,它将产生包含 CommonJS 要求表达式的无效 ESM 输出。【参考方案4】:
你想要一些有些矛盾的东西:
-
您要导入
package.json
,表示您将其视为源
但您不希望它像源代码那样被编译/发送到outDir
您不希望 outDir 中的输出路径包含“src/”,当您使 rootDir
指向项目根目录而不是 src
根目录时会发生这种情况,这是您可以做到的唯一方法让 import 语句生效。
解决方案:使用单独的 Typescript 子项目
如果您在逻辑上将项目分解为单独的子项目,这些矛盾就不会成为矛盾。您将需要 Typescript 3 的新 Project References 功能。
我们将src
目录和包含package.json
的根目录视为单独的项目。每个都有自己的tsconfig
文件:
为src
目录提供自己的项目。
./src/tsconfig.json
:
"compilerOptions":
"rootDir": ".",
"outDir": "../lib/",
"resolveJsonModule": true
,
"references": [ // this is how we declare a dependency from
"path": "../" // this project to the one at the root dir`
]
给根目录它自己的项目。
./tsconfig.json
:
"compilerOptions":
"rootDir": ".",
"outDir": ".", // if out path for a file is same as its src path, nothing will be emitted
"resolveJsonModule": true,
"composite": true // required on the dependency project for references to work
,
"files": [ // by whitelisting the files to include, TS won't automatically
"package.json" // include all source below root, which is the default.
]
因为根子项目的输出是同一个目录,并且package.json
的源路径和输出路径最终相同,tsc
不会做任何事情....实际上是一个否-op。
运行tsc --build src
,瞧!结果将是:
lib/
index.js
package.json
【讨论】:
【参考方案5】:指定compilerOptions.moduleResolution
、compilerOptions.resolveJsonModule
和include
,如下所示。
"compilerOptions":
// ...
"moduleResolution": "node",
"resolveJsonModule": true
// ...
,
"include": [
"./src",
"package.json"
]
然后在tsconfig.json文件所在的文件夹内运行$ tsc -b
,假设package.json
文件与 tsconfig.json
在同一路径
【讨论】:
以上是关于如何将 package.json 导入 Typescript 文件而不将其包含在编译输出中?的主要内容,如果未能解决你的问题,请参考以下文章
如何将react app创建为服务/程序包并将其导入另一个应用程序的'package.json'
可以在 Typescript 库中的 package.json 中将 @types 库作为正常依赖项吗?
错误 [ERR_PACKAGE_PATH_NOT_EXPORTED]:包子路径 './build/types' 未由 .../node_modules/jest-circus/package.json