首页 > 解决方案 > 在 Typescript 中防止不适当的导入和执行项目层次结构

问题描述

在 TS 项目中,我希望阻止以下内容:

我希望允许以下内容:

我知道参考资料。但是,据我了解,它们需要构建用于类型检查(如果进行了这种分离,则必须先构建以创建 d.ts 文件),我宁愿避免这种情况。

我有什么选择?是否可以简单地通过每个项目/文件夹的单独 tsconfig 文件来实现?

标签: typescriptdependency-managementtypescript3.0

解决方案


TLDR;你真的应该只使用参考。这正是他们的目的。

但是,让我们首先解决您的一些具体想法:

  1. 是否可以简单地通过每个项目/文件夹的单独 tsconfig 文件来实现?

    是的,但它不是很灵活。您可以通过将其设置为来隔离common。如果您尝试将projectA导入common ,则会出现错误。但是为了能够将common导入projectA,它必须更加全球化,但是这样您就可以导入projectBrootDir.'/path/to/projectA' is not under 'rootDir'rootDir

    不仅如此,根据项目参考文档:

    以前,如果您使用单个 tsconfig 文件,则使用此结构相当尴尬:

    • 实现文件可以导入测试文件
    • 不可能在没有出现在输出文件夹名称中的情况下同时构建test,这可能是您不想要的srcsrc
    • 仅更改实现文件中的内部结构需要再次对测试进行类型检查,即使这不会导致新的错误
    • 仅更改测试需要再次对实现进行类型检查,即使没有任何更改

    您可以使用多个 tsconfig 文件来解决其中一些问题,但会出现新问题

    • 没有内置的最新检查,所以你最终总是运行tsc两次
    • 调用tsc两次会导致更多的启动时间开销
    • tsc -w不能同时在多个配置文件上运行
  2. 我知道参考资料。但是,据我了解,它们需要构建用于类型检查(如果进行了这种分离,则必须先构建以创建 d.ts 文件),我宁愿避免这种情况。

    这种厌恶的原因是什么?

    • 如果这是构建新项目克隆的前期成本,那将远远超过改进的构建时间(参见下面的论点)。后者对开发人员生产力的好处将远远超过前者的成本。

      具有讽刺意味的是,您对前期成本的关注越大,缩短构建时间所带来的好处就越大!

    • 如果您希望能够在 VS Code 或 WebStorm 等类型和链接感知编辑器中导航新克隆而无需构建,您可以通过将.d.ts文件签入源代码控制来实现此目的。


    这是文档具体说的:

    由于依赖项目使用.d.ts从其依赖项构建的文件,因此您必须检查某些构建输出在克隆项目后构建项目,然后才能在编辑器中导航项目而不会看到虚假错误。我们正在开发一个应该能够缓解这种情况的幕后 .d.ts 生成过程,但现在我们建议通知开发人员他们应该在克隆后构建。

项目参考的论据

从文档:

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

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

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

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

    不必担心对您在命令行上传递的文件进行排序——tsc如果需要,将重新排序它们,以便始终首先构建依赖项。

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

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

Project References文档中有一些更有用的好处/功能。

示例设置

  • src/tsconfig.json

    即使您在根目录下没有代码,此 tsconfig 也可以是所有常用设置所在的位置(其他设置将从它继承),并且可以轻松tsc --build src构建整个项目(并--force从头开始构建它)。

    {
      "compilerOptions": {
        "rootDir": ".",
        "outDir": "../build",
        "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" }
        { "path": "./projectB" }
      ]
    }
    
    • src/common/tsconfig.json

      因为common没有引用,所以导入仅限于其目录中的目标和npm_modules. 我相信,你甚至可以通过赋予它自己的package.json.

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

      由于声明了引用,projectA可以导入common 。

          {
            "compilerOptions": {
              "rootDir": ".",
              "outDir": "../../build/projectA",
              "composite": true
            },
            "references": [
              { "path": "../common" }
            ]
          }
      
    • src/projectB/tsconfig.json

      由于声明了引用, projectB可以导入common AND projectA 。

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

构建

这些只是一些例子。tsc我使用以下开关的缩写形式,例如,-b 而不是--build. 从 repo 根目录执行的所有命令。

tsc -b src- 构建整个树。

tsc -p src/projectA/只编译 projectA。

tsc -b src/projectA/构建 projectA 和任何过期的依赖项。

tsc -b -w src- 建造并观看整棵树。

tsc -b --clean src- 删除整个树的输出。

tsc -b -f src- 强制重建整个树。

使用 -d-dry 开关预览tsc -b 将要执行的操作。


推荐阅读