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

dev*_*rts 7 node.js typescript yarnpkg yarn-workspaces

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

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

/cmd
/client
Run Code Online (Sandbox Code Playgroud)

我想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/**/*"
  ]
}
Run Code Online (Sandbox Code Playgroud)

与一个 package.json

{
  "name": "cmd",
  "version": "1.0.0",
  "dependencies": {
    "client": "^1.0.0",
  }
}
Run Code Online (Sandbox Code Playgroud)

在此模型中,cmdclient使用在tsconfig中设置的outDirsourceRoot字段进行编译。这意味着所有的编译的JavaScript进入dist/的子文件夹cmd/distclient/dist

如果我现在尝试和引用类clientcmd

import Foo from 'client/src/foo'
Run Code Online (Sandbox Code Playgroud)

IDE十分乐意解决此问题,因为它似乎是通过typescript references属性进行映射的。

但是,已编译的javascript归结为

const foo_1 = require("client/src/foo");
Run Code Online (Sandbox Code Playgroud)

但是,实际内置的javascript在中client/dist/src/foo,因此在运行时这永远无法工作。

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

任何人都无法阐明如何正确设置带有纱线工作区的Typescript 3.x monorepo,以使事情正常进行吗?

a13*_*300 55

我创建了一个 Github存储库,以便更容易地遵循以下代码描述:


代码说明

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


打字稿设置

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

{
  "references": [
    { "path": "./client" },
    { "path": "./cmd" }
  ],
  "files": [],
  "include": [],
  "exclude": ["**/node_modules"]
}
Run Code Online (Sandbox Code Playgroud)

为了正确指定构建顺序,我们需要向文件添加一个references属性cmd/tsconfig.json。这告诉编译器client/在我们编译之前它首先需要编译cmd/

cmd/tsconfig.json

{
  "extends": "../tsconfig.packages.json",
  "compilerOptions": {
    "rootDir": "src",
    "outDir": "dist"
  },
  "references": [
    {
      "path": "../client"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

建造顺序

client/
  ^
  |
  |
 cmd/
Run Code Online (Sandbox Code Playgroud)

节点设置

最佳实践是每个子项目都有自己的package.json文件,其中包含main属性和name集合。在我们的示例中,包 (cmd/client/) 都有一个main属性指向index.jsTypeScriptoutDir目录 (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
Run Code Online (Sandbox Code Playgroud)

client/packages.json

{
  "name": "client",
  "version": "1.0.0",
  "main": "dist/index",
  ...
}
Run Code Online (Sandbox Code Playgroud)

这是重要的,我们添加client/为依赖于cmd/packages.json这样的模块解析算法可以发现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
  }
}
Run Code Online (Sandbox Code Playgroud)

cmd/src/index.ts

import Foo from 'client';

console.log(Foo())
Run Code Online (Sandbox Code Playgroud)

纱线设置

纱线设置很容易。Yarn 将所有包添加到下面node_modules而不是:

  • cmd/node_modules
  • client/node_modules

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

<root>/package.json

{
  "private": true,
  "workspaces": [
    "cmd",
    "client"
  ],
  "name": "yarn_workplace",
  "version": "1.0.0"
  ...
}
Run Code Online (Sandbox Code Playgroud)

cmd/client/symlinked<root>/node_modules/目录:

纱线节点模块


笔记

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

  • 很好的答案。自从我发布问题以来,我也早就这样设置了。我最初的问题是不明白您必须拥有“dist”文件夹,如果您希望导入干净,则需要从索引模块导出它们。 (2认同)