“package.json"不在“rootDir"下 [英] 'package.json' is not under 'rootDir'

查看:53
本文介绍了“package.json"不在“rootDir"下的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在我的 TypeScript 应用程序中导入 package.json:

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

我的 tsconfig.json 包含以下内容:

<代码>{编译器选项":{"rootDir": "./src/""outDir": "./dist/","baseUrl": ".","resolveJsonModule": 真}}

问题是当我编译这个时,我得到

<块引用>

错误 TS6059:文件/path/to/package.json"不在rootDir"/path/to/app/src/"下.'rootDir' 应该包含所有源文件.

我不确定我是否理解这个问题,因为 ./src//.dist 都有相同的父 ..,所以 TypeScript 可以不理会 import '../package.json' 并且 它可以从 rootDiroutDir 工作.

无论如何,我尝试了以下方法,但结果并不令人满意:

  • remove rootDir - 编译有效,但 dist 将包含 dist/src,这是我不想要的
  • remove outDir - 然后 src.js 文件污染(还有 .js.map 如果 sourceMap 是真的)
  • add @ts-ignore - 编译停止导入../package.json
  • 的文件

此限制的解决方法是将生成的文件保留在 dist 中,并允许从 rootDir 的父目录导入?

解决方案

这是可能,结果证明,并不难.

解决方案不明显的原因是因为typescript依赖rootDir来决定输出的目录结构(见此评论来自 Typescript 的老板),并且只能导入包含在输出或包依赖项中的代码.>

  • 如果您将 rootDir 设置为项目的根目录,package.json 将被发送到 outDir 的根目录并可以导入.但是随后您编译的 src 文件被写入 outDir/src.
  • 如果将rootDir 设置为src,其中的文件将编译为outDir 的根目录.但是现在 编译器将没有地方发出 package.json,所以它会发出一个错误,因为项目似乎配置错​​误"(老板的话).

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

Typescript 项目tsconfig 文件定义,是自包含的,并且有效受其rootDir.这是一件非常好的事情,因为它符合封装原则.

你可以有多个项目(例如一个主库和一组库),每个项目都在自己的目录中,并有自己的 tsconfig.它们之间的依赖关系在 tsconfig 文件中使用 Typescript Project References 声明.

<块引用>

我承认,术语项目"是一个糟糕的词,因为它直观地指的是整个shebang,但是在这种情况下已经采用了模块"和包".将它们视为子项目",这样会更有意义.

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

  1. src 目录提供自己的项目.

    ./src/tsconfig.json:

    <代码>{编译器选项":{"rootDir": ".","outDir": "../dist/","resolveJsonModule": 真},"references": [//这就是我们声明依赖的方式{ "path": "../" }//这个项目到根目录的那个`]}

  2. 为根目录提供自己的项目.

    ./tsconfig.json:

    <代码>{编译器选项":{"rootDir": ".","outDir": ".",//如果文件的输出路径与其 src 路径相同,则不会发出任何内容"resolveJsonModule": 真,"composite": true//依赖项目需要引用才能工作},"files": [//通过将要包含的文件列入白名单,TS 不会自动"package.json"//包含根目录下的所有源代码,这是默认值.]}

  3. 运行 tsc --build src 和瞧!

    这将构建 src 项目.因为它声明了对根项目的引用,所以它也会构建那个,但前提是它已经过时了.因为根 tsconfig 与 outDir 具有相同的目录,tsc 将不会对 package.json 做任何事情,它被配置为编译的一个文件.

这对 monorepos 来说很棒

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

  • 您可以使用项目引用显式管理依赖项,以及模块化构建:

    来自链接的文档:

    • 您可以大大缩短构建时间
    <块引用>

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

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

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

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

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

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

这也很简单:

  • src/tsconfig.json

    即使你的根目录没有代码,这个 tsconfig 也可以放在所有的通用设置都去(其他人将从它继承),和它将启用一个简单的 tsc --build src 来构建整个项目(并使用 --force 从头开始​​构建它).

    <代码>{编译器选项":{"rootDir": ".","outDir": "../build/","resolveJsonModule": 真,复合":真},//这个根项目没有自己的源文件":[],//但构建此项目将构建以下所有内容:参考": [{路径":./common"}{路径":./projectA"}//在这里包含所有其他子项目]}

    • src/common/tsconfig.json

      因为 common 没有引用,所以导入仅限于其目录和 npm_modules 中的目标.我相信,您甚至可以通过为其提供自己的 package.json 来限制后者.

      <代码> {编译器选项":{"rootDir": ".","outDir": "../../build/common","resolveJsonModule": 真,复合":真}}

    • src/projectA/tsconfig.json

      projectA 可以导入 common 因为声明的引用.

      <代码> {编译器选项":{"rootDir": ".","outDir": "../../build/libA","resolveJsonModule": 真,复合":真},参考": [{路径":../common"}]}

I'm trying to import package.json in my TypeScript application:

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

My tsconfig.json contains the following:

{
  "compilerOptions": {
    "rootDir": "./src/"
    "outDir": "./dist/",
    "baseUrl": ".",
    "resolveJsonModule": true
  }
}

The problem is that when I compile this, I get

error TS6059: File '/path/to/package.json' is not under 'rootDir' '/path/to/app/src/'. 'rootDir' is expected to contain all source files.

I'm not sure I understand the issue, because both ./src/ and /.dist have the same parent .., so TypeScript could just leave alone the import '../package.json' and it would work from either rootDir or outDir.

Anyway, I've tried the following, with unsatisfactory results:

  • remove rootDir - compilation works, but the dist will contain dist/src, which I don't want
  • remove outDir - then src gets polluted with .js files (and .js.map if sourceMap was true)
  • add @ts-ignore - compilation stops the the file that imports ../package.json

What's the workaround for this limitation, to keep generated files in dist, and allow importing from the parent directory of rootDir?

解决方案

This is possible, and it turns out, not hard.

The reason the solution is not obvious is because typescript relies on the rootDir to decide the directory structure of the output (see this comment from Typescript's bossman), and only code included in the output or in package dependencies can be imported.

  • If you set rootDir to the root of your project, package.json gets emitted to the root of outDir and can be imported. But then your compiled src files get written to outDir/src.
  • If you set rootDir to src, files in there will compile to the root of outDir. But now the compiler won't have a place to emit package.json, so it issues "an error because the project appears to be misconfigured" (bossman's words).

solution: use separate Typescript sub-projects

A Typescript project is defined by a tsconfig file, is self-contained, and is effectively bounded by its rootDir. This is a very good thing, as it lines up with principles of encapsulation.

You can have multiple projects (e.g. a main and a set of libs) each in their own directory and with their own tsconfig. Dependencies between them are declared in the tsconfig file using Typescript Project References.

I admit, the term "projects" is a poor one, as intuitively it refers to the whole shebang, but "modules" and "packages" are already taken in this context. Think of them as "subprojects" and it will make more sense.

We'll treat the src directory and the root directory containing package.json as separate projects. Each will have its own tsconfig file.

  1. Give the src dir its own project.

    ./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. Give the root dir its own project.

    ./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. run tsc --build src and voilà!

    This will build the src project. Because it declares a reference to the root project, it will build that one also, but only if it is out of date. Because the root tsconfig has the same dir as the outDir, tsc will simply do nothing to package.json , the one file it is configured to compile.

this is great for monorepos

  • You can isolate modules/libraries/sub-projects by putting them in their own subdirectory and giving them their own tsconfig.

  • You can manage dependencies explicitly using Project References, as well as modularize the build:

    From the linked doc:

    • you can greatly improve build times

    A long-awaited feature is smart incremental builds for TypeScript projects. In 3.0 you can use the --buildflag with tsc. This is effectively a new entry point for tsc that behaves more like a build orchestrator than a simple compiler.

    Running tsc --build (tsc -b for short) will do the following:

    • Find all referenced projects
    • Detect if they are up-to-date
    • Build out-of-date projects in the correct order

    Don’t worry about ordering the files you pass on the commandline - tsc will re-order them if needed so that dependencies are always built first.

    • enforce logical separation between components

    • organize your code in new and better ways.

It's also very easy:

  • src/tsconfig.json

    Even if you have no code at the root, this tsconfig can be where all the common settings go (the others will inherit from it), and it will enable a simple tsc --build src to build the whole project (and with --force to build it from scratch).

    {
      "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

      Because common has no references, imports are limited to targets within its directory and npm_modules. You could even restrict the latter, I believe, by giving it its own package.json.

          {
           "compilerOptions": {
              "rootDir": ".",
              "outDir": "../../build/common",
              "resolveJsonModule": true,
              "composite": true
            }
          }
      

    • src/projectA/tsconfig.json

      projectA can import common because of the declared reference.

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

这篇关于“package.json"不在“rootDir"下的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆