如何将 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,它就可以工作。但是,如果您的 moduleES6/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.moduleResolutioncompilerOptions.resolveJsonModuleinclude,如下所示。


  "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

无法导入和使用 typescript socket.io

如何为所有节点模块自动安装@types

如何告诉 apollo codegen 查找查询的确切文件