如何使用带有打字稿和出文件夹的纱线工作区?

时间:2019-08-27 17:04:17

标签: node.js typescript yarnpkg yarn-workspaces

我正在尝试使用纱线建立一个单体仓库。我对如何使用项目引用设置打字稿感到困惑,以便正确解决问题。

例如,如果我有类似的文件夹结构

/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都进入dist/cmd/dist

client/dist子文件夹中

如果现在我尝试像这样从clientcmd中引用一个类,

import Foo from 'client/src/foo'

IDE很高兴解决此问题,因为它似乎是通过typescript references属性映射的。

但是,已编译的javascript可以归结为

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

但是,实际内置的javascript是在client/dist/src/foo中,因此在运行时这是行不通的。

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

任何人都无法阐明如何使用纱线工作区正确设置打字稿3.x monorepo,从而使事情正常进行吗?

2 个答案:

答案 0 :(得分:6)

我创建了一个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属性。这告诉编译器在编译client/之前首先需要编译cmd/

cmd/tsconfig.json

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

构建订单

client/
  ^
  |
  |
 cmd/


节点设置

最佳做法是每个子项目都有其自己的package.json文件,该文件具有main属性和name集。在我们的示例中,两个包(cmd/client/)都有一个main属性,该属性指向TypeScript outDir目录(index.js中的cmd/dist/index.js文件和client/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/ 作为依赖项添加到 cmd/packages.json ,因此模块解析算法在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())

node_modules


纱线设置

纱线设置简单。 Yarn将所有软件包添加到cmd/node_modules下,而不是:

  • client/node_modules
  • workspaces

要启用纱线workspaces,请将private: true属性和<root>/package.json属性添加到<root>/package.json文件中。

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

cmd/


client/symlinked软件包位于<root>/node_modules/目录下的cmd/

yarn node_modules


注释

  • 要启用代码导航,必须首先构建项目
  • 每个包裹都独立存在。 client/dist/index.d.ts包将定义文件 var nest = d3.nest() .key(function(d) { return d.region; }) .key(function(d) { return d.date; }) .rollup(function(leaves) { return d3.sum(leaves, function(d) { return parseInt(d.count, 10); }); }) .entries(dataset) 用于类型信息,而不是直接使用TypeScript文件。

答案 1 :(得分:-1)

我已经使用this repository中的Yarn Workspaces和Typescript在我的项目中使用了一些我一直使用的配置来设置了monorepo。

我不知道此设置是否可以解决您的问题,但您无需在Typescript配置中指定软件包。当您使用Yarn Workspaces时,它将在根node_modules的工作空间包属性中定义的根package.json中链接所有包:

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

yarn install之后,根node_modules具有clientcmd作为链接文件夹。

enter image description here

使用此配置,您可以简单地将任何软件包导入Workspace内的任何软件包。例如:

// cmd/src/index.ts

import { name } from 'client';

const otherName = 'cmd' + name;

console.log(otherName);