如何使用带有 typescript 和 out 文件夹的纱线工作区?

How to use yarn workspaces with typescript and out folders?

我正在尝试使用 yarn 设置一个 monorepo。我对如何使用项目引用设置打字稿以使事情正确解决感到困惑。

例如,如果我有这样的文件夹结构

/cmd
/client

我希望 cmd 依赖于 client 我可以:

cmd/tsconfig.json:

{
  "compilerOptions": {
    "types": ["reflect-metadata", "jest"],
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "moduleResolution": "node",
    "declaration": true,
    "importHelpers": true,
    "composite": true,
    "target": "esnext"
    "sourceRoot": "src",
    "outDir": "dist"
  },
  "references": [
    {
      "path": "../client"
    }
  ],
  "include": [
    "src/**/*"
  ]
}

package.json

{
  "name": "cmd",
  "version": "1.0.0",
  "dependencies": {
    "client": "^1.0.0",
  }
}

在此模型中,cmdclient 都在其 tsconfig 中使用 outDirsourceRoot 字段集进行编译。这意味着他们所有编译的 javascript 进入 cmd/distclient/dist

dist/ 子文件夹

如果现在我尝试将 client 中的 class 引用到 cmd 中,例如

import Foo from 'client/src/foo'

IDE 非常乐意解决这个问题,因为它似乎是通过打字稿 references 属性.

映射的

然而,编译后的 javascript 归结为

const foo_1 = require("client/src/foo");

然而,实际构建的 javascript 在 client/dist/src/foo 中,因此在运行时这永远不会起作用。

另一方面,如果我不使用 sourceRoots 和 outDirs,并且将 javascript 与同一文件夹中的打字稿文件内联,一切正常(但会使回购变脏并需要自定义 gitignores 来排除事物)

任何人都可以阐明如何使用 yarn 工作区正确设置 typescript 3.x monorepo 以便一切正常吗?

我已经设置了一个 monorepo I,其中包含我在 this repository.

中使用 Yarn Workspaces 和 Typescript 在我的项目中经常使用的一些配置

我不知道这个设置是否解决了你的问题,但你不需要在 Typescript 配置中指定你的包。当您使用 Yarn Workspaces 时,它会将您在根 node_modules 中定义的所有包链接到您在根 package.json 中定义的工作区包 属性:

"workspaces": {
    "packages": [
        "packages/**/*"
    ],
    "nohoist": []
}

yarn install 之后,根 node_modulesclientcmd 作为链接文件夹。

使用此配置,您可以简单地在工作区内的任何包中导入任何包。例如:

// cmd/src/index.ts

import { name } from 'client';

const otherName = 'cmd' + name;

console.log(otherName);

我创建了一个 Github Repository 以便更容易遵循以下代码说明:


代码说明

TypeScript Project References 可以编译由多个较小的 TypeScript 项目组成的 TypeScript 项目,每个项目都有一个 tsconfig.json 文件。 (来源:Project References Documentation


TypeScript 设置

我们有一个仅管理其子项目的根 tsconfig.json 文件。 references 属性 指定每个包含有效 tsconfig.json 文件的目录。如果我们现在使用 --build 选项 (tsc --build tsconfig.json) 构建项目,那么我们指定了应该编译的项目,但我们没有指定 构建顺序 应在其中编译项目。

{
  "references": [
    { "path": "./client" },
    { "path": "./cmd" }
  ],
  "files": [],
  "include": [],
  "exclude": ["**/node_modules"]
}

要正确指定 构建顺序,我们需要将 references 属性 添加到 cmd/tsconfig.json 文件。这告诉编译器在我们编译 cmd/:

之前它首先需要编译 client/

cmd/tsconfig.json:

{
  "extends": "../tsconfig.packages.json",
  "compilerOptions": {
    "rootDir": "src",
    "outDir": "dist"
  },
  "references": [
    {
      "path": "../client"
    }
  ]
}

构建顺序

client/
  ^
  |
  |
 cmd/

节点设置

最佳做法是每个子项目都有自己的 package.json 文件和 main property and the name set. In our example both packages (cmd/ and client/) have a main property pointing to the index.js file in the TypeScript outDir 目录(cmd/dist/index.jsclient/dist/index.js)。

项目结构:

tsconfig.json
cmd/
    tsconfig.json
    package.json
    src/
        index.ts
    dist/  #artifacts
        index.js
client/
    tsconfig.json
    package.json
    src/
        index.ts
    dist/  #artifacts
        index.js

client/packages.json

{
  "name": "client",
  "version": "1.0.0",
  "main": "dist/index",
  ...
}

重要 我们添加 client/ 作为对 [=42= 的依赖] 这样当我们在 TypeScript 代码中导入它时,模块解析算法可以找到 client/dist/index.js import Foo from 'client';:

cmd/packages.json

{
  "name": "cmd",
  "version": "1.0.0",
  "main": "dist/index",
  "dependencies": {
    "client": "1.0.0" // important
  }
}

cmd/src/index.ts

import Foo from 'client';

console.log(Foo())

纱线设置

纱线设置很简单。 Yarn 添加 node_modules 下的所有包,而不是:

  • cmd/node_modules
  • client/node_modules

要启用 yarn workspaces 添加 workspaces 属性 和 private: true 属性 到 <root>/package.json 文件。

<root>/package.json

{
  "private": true,
  "workspaces": [
    "cmd",
    "client"
  ],
  "name": "yarn_workplace",
  "version": "1.0.0"
  ...
}

cmd/client/包在<root>/node_modules/目录下symlinked:


备注

  • 要启用代码导航,必须先构建项目
  • 每个包都独立存在。 cmd/ 包使用定义文件 client/dist/index.d.ts 来获取类型信息,而不是直接使用 TypeScript 文件。