Prosjektreferanser i TypeScript 3 med separat `outDir`
Jeg vil gjerne bruke prosjektreferansefunksjonene i TypeScript 3.1. Katalogstrukturen til prosjektet mitt ser opprinnelig slik ut etter kompileringen:
.
├── A
│ ├── a.ts
│ ├── dist
│ │ ├── A
│ │ │ └── a.js
│ │ └── Shared
│ │ └── shared.js
│ └── tsconfig.json
└── Shared
├── dist
│ └── shared.js
├── shared.ts
└── tsconfig.json
Innholdet i Shared-katalogen:
shared.ts:
export const name = "name";
tsconfig.json:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"outDir": "dist",
"strict": true
}
}
Innholdet i A-katalogen:
a.ts:
import { name } from "../Shared/shared";
console.log(name);
tsconfig.json:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"outDir": "dist",
"strict": true
}
}
Og jeg kunne kjøre det med suksess ved å kjøre node dist/A/a.js i A-katalogen.
Det jeg ikke likte med dette, var at alt ble kopiert inn i A sitt utdata-katalog. Jeg trodde prosjektreferanser var her for å løse dette problemet.
For å aktivere prosjektreferanser, la jeg til følgende linje i Shared/tsconfig.json.
"composite": true
Og følgende til A/tsconfig.json:
"references": [
{ "path": "../Shared" }
]
Nå når jeg kompilere, er mappestrukturen som følger, noe jeg hadde forventet:
.
├── A
│ ├── a.ts
│ ├── dist
│ │ └── a.js
│ └── tsconfig.json
└── Shared
├── dist
│ ├── shared.d.ts
│ └── shared.js
├── shared.ts
└── tsconfig.json
Men når jeg kjører node dist/a.js i A-katalogen, får jeg følgende feil:
module.js:538
throw err;
^
Error: Cannot find module '../Shared/shared'
Grunnen er at i den genererte a.js-filen blir referansen til den importerte modulen ikke løst riktig:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var shared_1 = require("../Shared/shared");
console.log(shared_1.name);
Finnes det en måte å få det til å fungere uten å legge alle utdatafiler i samme katalog?
Eller, finnes det en bedre måte å organisere prosjektet mitt på for å bruke prosjektreferanser?
Svar #1
Faktisk er det en utfordring å få relative importstier til å fungere både for kildene dine og for output-filene. Den offisielle anbefalingen, hvis jeg forstår det riktig, er å sette opp en hovedutdata-katalog for hele det sammensatte prosjektet og ha Shared og A underkataloger inni den, slik at kildene og output-filene kan ha samme relative oppsett. Jeg vet ikke om det er det du mente du ikke ønsket å gjøre.
Det eneste andre alternativet jeg kjenner til, er å la hver komponent importere de andre komponentene (i ditt tilfelle har du bare A som importerer Delt) ved hjelp av ikke-relative importer som peker på utdatafiler (dvs. A/a.ts ville importert en sti som Delt/dist/delt). Siden du bruker ikke-relative importer, løses samme importsti som vises enten i kildefilen eller i den tilsvarende utdatafilen til samme målutdatafil. Importer løses ikke i IDE-en din før du har bygget det sammensatte prosjektet: dette er en kjent begrensning. Siden tsc ikke omskriver importene, må du sette opp runtime-miljøet og/eller bruke en bundler for å håndtere ikke-relative importer, og, om nødvendig, sette baseUrl og stier for TypeScript-kompilatoren til å matche.
Jeg vil gjerne hjelpe deg med detaljene i begge tilnærmingene om nødvendig; bare gi meg beskjed om hvor du står fast.
Svar #2
Den offisielle anbefalingen, hvis jeg forstår det riktig, er å sette opp en hovedutgangskatalog for hele det sammensatte prosjektet og ha Shared og A undermapper inne i den, slik at kildefilene og utdatafilene kan ha samme relative oppsett.
Matts svar er flott. For å følge opp kommentaren ovenfor, her er en måte å rekonfigurere A og Shared slik at den importerte modulen fungerer ordentlig.
A/tsconfig.json:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"outDir": "dist/A",
"strict": true
},
"references": [
{ "path": "../Shared" }
]
}
Shared/tsconfig.json:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"outDir": "../A/dist/Shared",
"composite": true,
"strict": true
}
}
Prosjektstrukturen etter tsc --build:
For å kjøre A, kjør node dist/A/a.js.
