【问题标题】:How to import package.json into Typescript file without including it in the compiled output?如何将 package.json 导入 Typescript 文件而不将其包含在编译输出中?
【发布时间】: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

【问题讨论】:

  • 接受的答案在写完一个月后就变成了不真实的。下面有两种可行的解决方案,应该接受其中一种。

标签: json typescript package.json


【解决方案1】:

当我只希望生成的 JS 文件使用实际的 package.json 时。

如果您的 src 文件的结构,您的 lib 将始终是一个直接副本。如果您将 package.json 包含到 TypeScript 编译上下文中,那么它会将您的库更改为 package.json + src

如何将 package.json 导入 Typescript 文件而不包含在编译输出中?

如果你导入它,你就不能。

另类

两个 项目,正如这个答案所提到的:https://stackoverflow.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】:

你想要一些有些矛盾的东西:

  1. 您要导入package.json,表示您将其视为源
  2. 但您不希望它像源代码那样被编译/发送到outDir
  3. 您不希望 outDir 中的输出路径包含“src/”,当您使 rootDir 指向项目根目录而不是 src 根目录时会发生这种情况,这是您可以做到的唯一方法让 import 语句生效。

解决方案:使用单独的 Typescript 子项目

如果您在逻辑上将项目分解为单独的子项目,这些矛盾就不会成为矛盾。您将需要 Typescript 3 的新 Project References 功能。

我们将src 目录和包含package.json 的根目录视为单独的项目。每个都有自己的tsconfig 文件:

  1. 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`
       ]
     }
    
  2. 给根目录它自己的项目。

    ./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。

  3. 运行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在同一路径

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-24
      • 2017-04-12
      • 2018-04-23
      • 2017-02-05
      • 1970-01-01
      • 2020-03-31
      • 2018-11-22
      • 2017-12-03
      相关资源
      最近更新 更多