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.

Relaterte artikler