Как работает инкрементная компиляция gulp-typcript?
README от gulp-typcript говорит, что поддерживает инкрементную компиляцию, но не объясняет, что означает этот термин в данном контексте.
Есть проблема, обсуждающая, как инкрементная компиляция gulp-typcript медленнее, чем tsc, но она не объясняет, почему или в чем разница.
Что делает gulp-typcript, когда выполняет "инкрементную компиляцию"?
Что я пробовал
Я смотрю на исходный код gulp-typcript и похоже, что gulp-typcript вообще не выполняет никакой дополнительной компиляции. Когда Project
создается, он закрывается над экземпляром ProjectInfo
, который имеет input
член, который является FileCache
, FileCache - это в значительной степени отображение имен файлов в исходные строки. Существует не так много другого состояния, которое поддерживается в gulp-машинописи Project
,
Чтобы выполнить фактическую инкрементную компиляцию (повторное использование продуктов процесса компиляции в последующих сборках) с использованием API компилятора TS, я ожидал увидеть одно из следующего:
- С помощью
ts.createWatchCompilerHost
API - С помощью
ts.createLanguageService
Но я не вижу ни одного из них в источнике.
2 ответа
Gulp-typcript имеет два разных способа компиляции ваших файлов. Метод по умолчанию компилирует весь проект и выполняет проверку типов. Это реализовано в ProjectCompiler
в lib/compiler.ts
, Другой компилирует каждый файл отдельно и активируется при установке isolatedModules: true
, Этот метод реализован в FileCompiler
в lib/compiler.ts
,
FileCompiler нужно только скомпилировать файлы, которые были изменены. Неизмененные файлы кешируются, как описал Ахмеджанов в своем ответе.
Однако большинство пользователей используют ProjectCompiler, поскольку проверка типов, вероятно, является причиной того, что они используют TypeScript. Я думаю, что ваш вопрос касается этого ProjectCompiler. Инкрементная компиляция обрабатывается вызовом ts.createProgram
, который экспортирует API TypeScript. Передав старую программу, API-интерфейс TypeScript будет повторно использовать некоторую информацию из предыдущей компиляции. Вы можете найти исходный код здесь:
Раньше этого было достаточно, чтобы получить пошаговую компиляцию, но это изменилось в новых версиях TypeScript. Нам нужно будет переключиться на новый API, возможно, используя один из упомянутых вами API, но я не знаком с ними.
В своем вопросе вы упомянули FileCache. Это используется для хранения всех файлов, которые передаются во входном потоке. API gulp предоставляет все файлы в потоке, тогда как API TypeScript является синхронным. Таким образом, нам нужно подождать, пока у нас будут все входные файлы. Кроме того, мы используем FileCache в FileCompiler, чтобы определить, изменился ли файл и, следовательно, нужно ли его перекомпилировать.
gulp-typcript кэширует скомпилированные js-файлы, при изменении какого-либо файла он компилирует один 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,
});
Даже одна компиляция файла вызывает анализ импортированных зависимостей, поэтому она не может быть быстрее, чем tsc --watch