“ package.json”不在“ rootDir”下

时间:2019-04-18 20:16:13

标签: javascript typescript

我正在尝试在Typescript应用程序中读取package.json。现在,我的tsconfig.json包含以下内容:

"outDir": "dist",
"baseUrl": ".",
"rootDir": "src/",

当我编译它时,我得到File '/Path/to/package.json' is not under 'rootDir' '/Path/To/App/src/'. 'rootDir' is expected to contain all source files.

我理解这个问题,并且如果我要删除rootDir,则所有内容都可以使用,除了dist包含不需要的dist/src

这有什么解决方法?

5 个答案:

答案 0 :(得分:14)

这是可能,事实证明,并不困难

解决方案之所以不明显,是因为打字稿依靠rootDir来决定输出的目录结构(请参见this comment from Typescript's bossman),并且仅包含代码可以导入输出或包中的依赖项。

  • 如果将rootDir设置为项目的根目录,则会将package.json发送到outDir的根目录并可以导入。但是之后,您编译的src文件将被写入outDir/src
  • 如果将rootDir设置为src,则其中的文件将编译到outDir的根目录。但是现在the compiler won't have a place to emit package.json发出了“由于项目配置错误而产生的错误”(老板的话)。

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

Typescript项目 tsconfig 文件定义,是自包含的,并且受其rootDir有效地限制。这很不错,因为它符合封装原理

您可以在各自的目录中和各自的tsconfig中拥有多个项目(例如,一个主库和一组lib)。它们之间的依赖关系使用Typescript Project References在tsconfig文件中声明。

我承认,术语“项目”是一个可怜的词,直觉上是指整个shebang,但是在这种情况下已经采用了“模块”和“包”。将它们视为“子项目”,这样会更有意义。

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

  1. src目录赋予其自己的项目。

    ./src/tsconfig.json

    {
      "compilerOptions": {
        "rootDir": ".",
        "outDir": "../dist/",
        "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.
      ]
    }
    
  3. 运行tsc --build src并加油!

    这将构建src项目。因为它声明了对根项目的引用,所以它也会构建该项目,但前提是该项目已过时。因为根tsconfig的目录与outDir相同,所以tsc只会对package.json(配置为要编译的一个文件)不做任何操作。

这对monorepos非常有用

  • 您可以通过将模块/库/子项目放在自己的子目录中并为其提供自己的tsconfig来隔离它们。

  • 您可以使用Project References显式管理依赖关系,也可以模块化构建:

    从链接的文档中:

    • 您可以大大缩短构建时间

    期待已久的功能是用于TypeScript项目的智能增量构建。在3.0中,您可以将--build标志与tsc一起使用。实际上,这是tsc的新入口点,其行为更像是构建协调器,而不是简单的编译器。

    运行tsc --build(简称为tsc -b)将执行以下操作:

    • 找到所有引用的项目
    • 检测是否为最新
    • 以正确的顺序构建过时的项目

    不用担心对在命令行上传递的文件进行排序-tsc会在需要时对它们进行重新排序,以便始终先构建依赖项。

    • 加强组件之间的逻辑分离

    • 以更好的新方式组织代码。

这也很容易:

  • src/tsconfig.json

    即使您的根目录没有代码,此tsconfig也可以放在 所有通用设置都将被使用(其他设置将从其继承),并且 它将使简单的tsc --build src能够构建整个 项目(并使用--force从头开始构建它)。

    {
      "compilerOptions": {
        "rootDir": ".",
        "outDir": "../build/",
        "resolveJsonModule": true,
        "composite": true
      },
      // this root project has no source of its own
      "files": [],
      // but building this project will build all of the following:
      "references": [
        { "path": "./common" }
        { "path": "./projectA" }
        // include all other sub-projects here  
      ]
    }
    
    • src/common/tsconfig.json

      由于 common 没有引用,因此导入仅限于其目录和npm_modules中的目标。我相信,您甚至可以给它自己的package.json来限制后者。

          {
           "compilerOptions": {
              "rootDir": ".",
              "outDir": "../../build/common",
              "resolveJsonModule": true,
              "composite": true
            }
          }
      
    • src/projectA/tsconfig.json

      由于声明了引用,

      projectA 可以导入 common

          {
            "compilerOptions": {
              "rootDir": ".",
              "outDir": "../../build/libA",
              "resolveJsonModule": true,
              "composite": true
            },
            "references": [
              { "path": "../common" }
            ]
          }
      

答案 1 :(得分:9)

我们可以将resolveJsonModule设置为false并在*.json内为typings.d.ts声明一个模块,这将需要JSON文件作为模块,并且它将生成{{1 }}目录。

Monorepo目录结构

dist

monorepo\ ├─ app\ │ ├─ src\ │ │ └─ index.ts │ ├─ package.json │ ├─ tsconfig.json │ └─ typings.d.ts └─ lib\ └─ package.json

app/typings.d.ts

declare module "*.json";

app/src/index.ts

// Import from app/package.json import appPackageJson from '../package.json'; // Import from lib/package.json import libPackageJson from '../../lib/package.json'; export function run(): void { console.log(`App name "${appPackageJson.name}" with version ${appPackageJson.version}`); console.log(`Lib name "${libPackageJson.name}" with version ${libPackageJson.version}`); } run(); 内容

package.json

现在,如果我们使用app/package.json { "name": "my-app", "version": "0.0.1", ... { lib/package.json { "name": "my-lib", "version": "1.0.1", ... } 编译项目,则将获得以下tsc目录结构:

dist

如果我们使用app\ └─ dist\ ├─ index.d.ts └─ index.js 运行它,我们将从node ./distapp lib信息中获取输出:

package.json

您可以在这里找到项目存储库:https://github.com/clytras/typescript-monorepo

答案 2 :(得分:2)

目前不可能。 Typescript编译器尝试保持目录结构。

例如,您的项目如下:

src/
  shared/
    index.ts
  index.ts
package.json
tsconfig.json

您的tsconfig.json包含:

{
  "compilerOptions": {
    "outDir": "./build",
    "module": "commonjs",
    "target": "es6",
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "noImplicitAny": true,
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true
  },
  "include": [
    "src/**/*"
  ]
}

如您所见,文件不包含rootDir属性,但是当您调用tsc命令来编译项目时,输出将类似于:

build/
  shared/
    index.js
  index.js

输出不包含src文件夹,因为在我的代码中,我只是导入并在src文件夹中使用,例如:

src/index.ts

import someName from './shared';

然后,build/index.js如下所示:

...
const shared_1 = __importDefault(require("./shared"));
...

如您所见-require("./shared"),这意味着它可以与build文件夹结构配合使用。

当您导入“外部”模块时,您的“问题”出现了

import packageJson from '../package.json';

那么,“后退”动作-“ ../”会发生什么?如果您希望输出结构为:

build/
  package.json
  index.js

然后,它们如何与const packageJson = __importDefault(require("../package.json"));一起使用。然后,Typescript编译器尝试保持项目结构:

build/
  package.json
  src/
    index.js

对于一个monorepo项目,我认为您需要为每个库创建声明文件,然后在tsconfig文件中使用references设置。例如:

  1. ./lib01文件夹中,lib在其代码中导入./lib02。 Tsconfig文件将类似于:
{
  "compilerOptions": {
    "declarationDir": "dist",
    "rootDir": "src"
  },
  "include": ["src/**/*"],
  "references": [ // here
    {
      "path": "../lib02"
    }
  ]
}
  1. lib02的tsconfig.json
 {
   "compilerOptions": {
    "declarationDir": "dist",
    "rootDir": "src",
    "composite": true // importance.
  }
 }

答案 3 :(得分:0)

这取决于您阅读“ package.json”的方式和时间。您可以在运行时使用NodeJS“ fs”模块将其读取为文件,或者只需键入const package = require(“ package.json”)。

在第二种情况下,Typescript将在编译时在root目录中对其进行搜索(请参阅Typescript module resolution文档)。

您还可以使用“ rootDirs”属性代替“ rootDir”来指定根文件夹的数组。

答案 4 :(得分:0)

我通过使用符号链接解决了这个问题: 在窗口中:

cd src
mklink package.json ..\package.json

或在 linux 中:

cd src
ln -s package.json ../package.json