gulp-typescript's README says it supports incremental compilation but doesn't explain what is meant by that term in this context.
There's an issue discussing how gulp-typescript incremental compilation is slower than tsc, but it doesn't explain why, or what the difference is.
What is gulp-typescript doing when it does "incremental compilation"?
I'm looking at gulp-typescript's source code and it looks like gulp-typescript isn't doing any incremental compilation at all.
When a Project
is created, it closes over an instance of ProjectInfo
, which has an input
member which is a FileCache
. A FileCache is pretty much a mapping from file names to source strings. There isn't much other state that is maintained in a gulp-typescript Project
.
In order to do actual incremental compilation (reusing products of the compilation process in subsequent builds) using the TS compiler API, I would expect to see one of the following:
ts.createWatchCompilerHost
API
ts.createLanguageService
But I don't see either of those in the source.
Gulp-typescript has two different ways to compile your files. The default method compiles the whole project and does type checking. This is implemented in ProjectCompiler
in lib/compiler.ts
. The other compiles each file separate, and is activated when you set isolatedModules: true
. That method is implemented in FileCompiler
in lib/compiler.ts
.
The FileCompiler only needs to compile the files which are changed. Unchanged files are cached, like Achmedzhanov described in his answer.
Most users however use the ProjectCompiler, as type checking is probably the reason that they are using TypeScript. I think that your question regards this ProjectCompiler. Incremental compilation is handled by the call to ts.createProgram
, which the TypeScript API exports. By passing the old program, the TypeScript API would reuse some of the information of the previous compilation. You can find the source code here:
https://github.com/ivogabe/gulp-typescript/blob/ea22fb7fe4295979e32a9d07b007e3f7473be8b5/lib/compiler.ts#L80
That used to be enough to get incremental compilation, but that has changed in newer versions of TypeScript. We will need to switch to a new API, probably using one of the APIs you mentioned, but I'm not familiar with those.
In your question you mentioned the FileCache. This is used to store all files that are passed in the input stream. The gulp API namely gives all files in a stream, whereas the TypeScript API is synchronous. We thus need to wait until we have all input files. Furthermore, we use the FileCache in the FileCompiler to detect whether a file has changed and thus whether we need to recompile it.
gulp-typescript caches compiled js files, when some file is changed then it compiles one 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,
});
Even one file compilation causes analysis of imported dependecies so it couldn't be faster then tsc --watch
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With