Monorepo 与 `rootDirs` 会产生不需要的子目录,例如 `outDir` 中的 `src`

Jeo*_*eon 5 dependencies typescript tsconfig monorepo

我正在计划一个 monorepo typescript 项目,如下所示:

/ (root)
+--backend/
|  +-src/
|  \-tsconfig.json
+--shared/
|  \-src/
\--frontend/
   \-src/
Run Code Online (Sandbox Code Playgroud)

tsconfig.json定义如下:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "outDir": "./dist",
    "strict": true,
    "baseUrl": "./src",
    "paths": {
      "shared": [
        "../../shared/src"
      ]
    },
    "rootDirs": [
      "./src",
      "../shared/src"
    ],
    "esModuleInterop": true
  }
}
Run Code Online (Sandbox Code Playgroud)

tsc当我在它下面执行时backend,如下所示:

/ (root)
+-backend/
  +-dist/
  | +-backend/
  | | +-src/
  | \-shared/
  |   \-src/
  +-src/
  \-tsconfig.json
Run Code Online (Sandbox Code Playgroud)

在上面,dist包含backendshared但它们每个都包含src在它下面。我想要backendshared包含dist已编译的 JS 文件,但不包含src

/ (root)
+-backend/
  +-dist/
  | +-backend/
  | \-shared/
  +-src/
  \-tsconfig.json
Run Code Online (Sandbox Code Playgroud)

是否可以 ?我怎样才能做到呢?

vas*_*vas 20

诊断

\n
    \n
  • Typescript 依赖rootDir(而不是rootDirs)来决定输出的目录结构(请参阅Typescript\'s bossman 的评论)。
  • \n
  • 当您设置多个时rootDirstsc将找到所有这些目录共有的父目录并将视为rootDir. 这就是为什么你会得到outDir这样的结构。
  • \n
\n
\n

处方:将您的单一存储库构建为单独的 Typescript 子项目

\n

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

\n

您可以拥有多个项目(例如,一个主项目和一组库),每个项目都在自己的目录中,具有自己的 tsconfig、自己的rootDir. 它们之间的依赖关系在 tsconfig 文件中使用 Typescript Project References进行管理。

\n
\n

不幸的是,Typescript 人员选择了“项目”这个术语,因为直观上它指的是整个项目,但“模块”和“包”已经被采用了。但如果你将它们视为子项目,那就更有意义了。

\n
\n

但我建议您像这样构建您的存储库:

\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 dist\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 src\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 tsconfig.json\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 shared\n    \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 index.ts\n    \xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 tsconfig.json\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 backend\n    \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 index.ts\n    \xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 tsconfig.json\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 frontend\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 index.ts\n        \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 tsconfig.json \n
Run Code Online (Sandbox Code Playgroud)\n

这样,当您编译代码时,您将得到:

\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 dist\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 shared\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 backend\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 frontend\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 src\n
Run Code Online (Sandbox Code Playgroud)\n

tsconfig 示例

\n
    \n
  • src/tsconfig.json

    \n

    即使您在根目录下没有代码,这个 tsconfig 也可以是所有通用设置所在的位置(其他设置将从它继承),并且\n将允许简单地tsc --build src构建整个项目(并使用--force可以从划痕)。

    \n
      {\n    "compilerOptions": {\n      "rootDir": ".",\n      "outDir": "../dist/",\n    },\n    "files": [],\n    "references": [\n      { "path": "./shared" },\n      { "path": "./backend" },\n      { "path": "./frontend" }\n    ]\n  }\n
    Run Code Online (Sandbox Code Playgroud)\n
      \n
    • src/shared/tsconfig.json

      \n

      共享不会导入任何其他项目,因为它没有引用。它导入的所有内容都仅限于其目录和\n中列出的依赖项package.json。你甚至可以限制后者,我相信,通过给它自己的package.json

      \n
        {\n    "compilerOptions": {\n      "rootDir": ".",\n      "outDir": "../../dist/shared",\n      "composite": true\n    }\n  }\n
      Run Code Online (Sandbox Code Playgroud)\n
    • \n
    • src/backend/tsconfig.json

      \n

      后端可以导入共享由于声明的引用,

      \n
        {\n    "compilerOptions": {\n      "rootDir": ".",\n      "outDir": "../../dist/backend",\n      "composite": true\n    },\n    "references": [\n      { "path": "../shared" }\n    ]\n  }\n
      Run Code Online (Sandbox Code Playgroud)\n
    • \n
    • src/frontend/tsconfig.json

      \n

      前端可以导入共享后端由于声明的引用,

      \n
        {\n    "compilerOptions": {\n      "rootDir": ".",\n      "outDir": "../../dist/frontend",\n      "composite": true\n    },\n    "references": [\n      { "path": "../shared" },\n      { "path": "../backend" }\n    ]\n  }\n
      Run Code Online (Sandbox Code Playgroud)\n
    • \n
    \n
  • \n
\n

构建命令示例

\n

tsc --build src将构建整个 src 树

\n

tsc --build src/backend将构建后端并共享(如果自上次构建以来有更改)。

\n

  • 只是想大声喊出这个出色的答案,这是在博客文章中探索不同的参考项目结构一天后唯一对我有用的答案。 (2认同)