Hur fungerar gulp-typescript inkrementell kompilering?
gulp-typescripts README säger att det stöder inkrementell kompilering men förklarar inte vad som menas med den termen i detta sammanhang.
Det finns en fråga om hur gulp-typescript inkrementell kompilering är långsammare än tsc, men den förklarar inte varför, eller vad skillnaden är.
Vad gör gulp-typescript när det utför "inkrementell kompilering"?
Vad jag försökte
Jag tittar på gulp-typescripts källkod och det ser ut som att gulp-typescript inte gör någon inkrementell kompilering alls. När ett Project skapas, stänger det över en instans av ProjectInfo, som har en input-medlem som är en FileCache. En FileCache är i princip en mappning från filnamn till källsträngar. Det finns inte mycket annan tillstånd som underhålls i ett gulp-typescript Project.
För att göra faktisk inkrementell kompilering (återanvända produkter från kompilationsprocessen i efterföljande byggnader) med TS-kompilator-API:et, skulle jag förvänta mig att se en av följande:
- Använda
ts.createWatchCompilerHost-API:et - Använder
ts.createLanguageService
Men jag ser inte någon av dem i källan.
Svar #1
Gulp-typescript har två olika sätt att kompilera dina filer. Standardmetoden kompilerar hela projektet och gör typkontroll. Detta är implementerat i ProjectCompiler i lib/compiler.ts. Den andra kompilerar varje fil separat och aktiveras när du sätter isolatedModules: true. Den metoden är implementerad i FileCompiler i lib/compiler.ts.
FileCompiler behöver bara kompilera de filer som har ändrats. Oförändrade filer cachas, som Achmedzhanov beskrev i sitt svar.
De flesta användare använder dock ProjectCompiler, eftersom typkontroll förmodligen är anledningen till att de använder TypeScript. Jag tror att din fråga gäller denna ProjectCompiler. Inkrementell kompilering hanteras av anropet till ts.createProgram, som TypeScript API exporterar. Genom att skicka det gamla programmet skulle TypeScript API återanvända viss information från den tidigare kompileringen. Du kan hitta källkoden här:
https://github.com/ivogabe/gulp-typescript/blob/ea22fb7fe4295979e32a9d07b007e3f7473be8b5/lib/compiler.ts#L80
Det brukade räcka för att få inkrementell kompilering, men det har förändrats i nyare versioner av TypeScript. Vi kommer att behöva byta till ett nytt API, förmodligen genom att använda ett av de API:er du nämnde, men jag är inte bekant med dem.
I din fråga nämnde du FileCache. Detta används för att lagra alla filer som skickas i inmatningsströmmen. Gulp API:n ger nämligen alla filer i en ström, medan TypeScript API:n är synkron. Vi behöver därför vänta tills vi har alla inmatningsfiler. Dessutom använder vi FileCache i FileCompiler för att upptäcka om en fil har förändrats och därmed om vi behöver kompilera om den.
Svar #2
gulp-typescript cacher kompilerade js-filer, när någon fil ändras så kompilerar den en https://github.com/ivogabe/gulp-typescript/blob/master/lib/compiler.ts#L282
if (this.project.input.getFileChange(file.fileNameOriginal).state === FileChangeState.Equal) {
// Not changed, re-use old file.
const old = this.previousOutput[file.fileNameNormalized];
this.write(file, old.fileName, old.diagnostics, old.content, old.sourceMap);
return;
}
const output: ts.TranspileOutput = this.project.typescript.transpileModule(file.content, {
compilerOptions: this.project.options,
fileName: file.fileNameOriginal,
reportDiagnostics: true,
transformers: this.finalTransformers ? this.finalTransformers() : undefined,
});
Även en filkompilering orsakar analys av importerade beroenden, så det kunde inte gå snabbare än tsc --watch
