问题
I am planning a monorepo typescript porject like below:
/ (root)
+--backend/
| +-src/
| \-tsconfig.json
+--shared/
| \-src/
\--frontend/
\-src/
tsconfig.json is defined like below:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"outDir": "./dist",
"strict": true,
"baseUrl": "./src",
"paths": {
"shared": [
"../../shared/src"
]
},
"rootDirs": [
"./src",
"../shared/src"
],
"esModuleInterop": true
}
}
When I execute tsc under backend it gives me like below:
/ (root)
+-backend/
+-dist/
| +-backend/
| | +-src/
| \-shared/
| \-src/
+-src/
\-tsconfig.json
In the above, dist contains backend and shared BUT each of them contains src under it. I wanted backend and shared under dist contain compiled JS files without src:
/ (root)
+-backend/
+-dist/
| +-backend/
| \-shared/
+-src/
\-tsconfig.json
Is it possible ? And how can I make it ?
回答1:
diagnosis
- Typescript relies on
rootDir(notrootDirs) to decide the directory structure of the output (see this comment from Typescript's bossman). - When you set multiple
rootDirs,tscwill find the parent directory that is common to all of them and treat that a therootDir. This is why you're getting theoutDirstructure that you're getting.
prescription: Structure your monorepo as separate Typescript sub-projects
A Typescript project is defined by a tsconfig file, is self-contained, and is effectively bounded by its rootDir. This is a very good thing, as it lines up with principles of encapsulation.
You can have multiple a projects (e.g. a main and a set of libs) each in their own directory with their own tsconfig, with their own rootDir. Dependencies between them are managed in the tsconfig files using Typescript Project References.
It's unfortunate that the Typescript folks chose the term "projects", as intuitively it refers to the whole shebang, but "modules" and "packages" was already taken. But if you think of them as subprojects and it will make a lot more sense.
But I recommend you structure your repo like so:
.
├── dist
└── src
├── tsconfig.json
├── shared
│ ├── index.ts
│ └── tsconfig.json
├── backend
│ ├── index.ts
│ └── tsconfig.json
└── frontend
├── index.ts
└── tsconfig.json
So that when you compile your code you get:
.
├── dist
│ ├── shared
│ ├── backend
│ └── frontend
└── src
Example tsconfigs
src/tsconfig.jsonEven if you have no code at the root, this tsconfig can be where all the common settings go (the others will inherit from it), and it will enable a simple
tsc --build srcto build the whole project (and with--forceto build it from scratch).{ "compilerOptions": { "rootDir": ".", "outDir": "../dist/", }, "files": [], "references": [ { "path": "./shared" }, { "path": "./backend" }, { "path": "./frontend" } ] }src/shared/tsconfig.jsonshared won't import any of the other projects as it has no references. All it imports are limited to within its directory and dependencies listed in
package.json. You could even restrict the the latter, I believe, by giving it its ownpackage.json.{ "compilerOptions": { "rootDir": ".", "outDir": "../../dist/shared", "composite": true } }src/backend/tsconfig.jsonbackend can import shared because of the declared reference.
{ "compilerOptions": { "rootDir": ".", "outDir": "../../dist/backend", "composite": true }, "references": [ { "path": "../shared" } ] }src/frontend/tsconfig.jsonfrontend can import shared AND frontend because of the declared references.
{ "compilerOptions": { "rootDir": ".", "outDir": "../../dist/frontend", "composite": true }, "references": [ { "path": "../shared" }, { "path": "../backend" } ] }
Example build commands
tsc --build src will build the entire src tree
tsc --build src/backend will build the the backend AND shared (if there have been changes since the last build.
来源:https://stackoverflow.com/questions/60896829/monorepo-with-rootdirs-produces-unwanted-sudirectories-such-as-src-in-outdi