Use tsgo to run type checks on client for watch#296215
Use tsgo to run type checks on client for watch#296215mjbvz wants to merge 3 commits intomicrosoft:mainfrom
tsgo to run type checks on client for watch#296215Conversation
This reduces the time to get `src` transpiled and fully type checked to around 15seconds on my machine
| "allowJs": true, | ||
| "resolveJsonModule": true, | ||
| "isolatedModules": false, | ||
| "skipLibCheck": true, |
There was a problem hiding this comment.
adding this temporarily to work around microsoft/tas-client#88
There was a problem hiding this comment.
Pull request overview
Updates the development watch pipeline to use tsgo for client type-checking (in esbuild-transpile mode) to reduce end-to-end watch latency.
Changes:
- Enable
skipLibCheckinsrc/tsconfig.jsonto reduce type-check overhead. - Add a new
watchTypeCheckTaskthat runstsgo --noEmiton changes. - Switch
gulp watch-client(esbuild-transpile mode) to use the new tsgo-based watcher.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/tsconfig.json | Enables skipLibCheck to reduce type-check cost. |
| build/lib/tsgo.ts | Adjusts tsgo completion/error reporting output behavior. |
| build/lib/compilation.ts | Introduces watchTypeCheckTask that debounces tsgo no-emit checks on file changes. |
| build/gulpfile.ts | Wires watch-client (esbuild mode) to use watchTypeCheckTask instead of the old gulp-tsb watcher. |
| const watchClientTask = useEsbuildTranspile | ||
| ? task.define('watch-client', task.parallel(compilation.watchTask('out', false, 'src', { noEmit: true }), compilation.watchApiProposalNamesTask, compilation.watchExtensionPointNamesTask, compilation.watchCodiconsTask)) | ||
| ? task.define('watch-client', task.parallel(compilation.watchTypeCheckTask('src'), compilation.watchApiProposalNamesTask, compilation.watchExtensionPointNamesTask, compilation.watchCodiconsTask)) | ||
| : task.define('watch-client', task.series(util.rimraf('out'), task.parallel(compilation.watchTask('out', false), compilation.watchApiProposalNamesTask, compilation.watchExtensionPointNamesTask, compilation.watchCodiconsTask))); |
There was a problem hiding this comment.
In esbuild-transpile mode, watch-client is now only running the tsgo typecheck watcher plus the metadata/codegen watchers. If nothing else in this task graph is generating/updating src/vs/monaco.d.ts (and related generated files) on change, that’s a regression from the previous compilation.watchTask(..., { noEmit: true }) behavior.
Either ensure watchTypeCheckTask handles Monaco d.ts generation (preferred), or add a dedicated generator watch task here.
| export function watchTypeCheckTask(src: string): task.StreamTask { | ||
| const theTask = () => { | ||
| const projectPath = path.join(import.meta.dirname, '../../', src, 'tsconfig.json'); | ||
| const watchInput = watch(`${src}/**`, { base: src, readDelay: 200 }); | ||
| const tsgoStream = watchInput.pipe(util.debounce(() => { | ||
| const stream = createTsgoStream(projectPath, { taskName: 'watch-client-noEmit', noEmit: true }); | ||
| const result = es.through(); | ||
| stream.on('end', () => result.emit('end')); | ||
| stream.on('error', () => result.emit('end')); | ||
| return result; | ||
| })); | ||
| return tsgoStream; | ||
| }; |
There was a problem hiding this comment.
watchTypeCheckTask replaces the old watchTask(..., { noEmit: true }) path, but it no longer runs MonacoGenerator in watch mode. That means src/vs/monaco.d.ts / standaloneEnums.ts won’t be auto-regenerated on relevant changes during gulp watch-client (esbuild mode), which previously happened via watchTask.
Consider invoking new MonacoGenerator(true).execute() (and keeping its file watchers alive) inside watchTypeCheckTask, or otherwise ensuring an equivalent Monaco d.ts generation step is still part of watch-client.
| export function watchTypeCheckTask(src: string): task.StreamTask { | ||
| const theTask = () => { | ||
| const projectPath = path.join(import.meta.dirname, '../../', src, 'tsconfig.json'); | ||
| const watchInput = watch(`${src}/**`, { base: src, readDelay: 200 }); | ||
| const tsgoStream = watchInput.pipe(util.debounce(() => { | ||
| const stream = createTsgoStream(projectPath, { taskName: 'watch-client-noEmit', noEmit: true }); | ||
| const result = es.through(); | ||
| stream.on('end', () => result.emit('end')); | ||
| stream.on('error', () => result.emit('end')); | ||
| return result; | ||
| })); | ||
| return tsgoStream; | ||
| }; |
| const projectPath = path.join(import.meta.dirname, '../../', src, 'tsconfig.json'); | ||
| const watchInput = watch(`${src}/**`, { base: src, readDelay: 200 }); | ||
| const tsgoStream = watchInput.pipe(util.debounce(() => { | ||
| const stream = createTsgoStream(projectPath, { taskName: 'watch-client-noEmit', noEmit: true }); |
There was a problem hiding this comment.
Is incremental or not? Like, will every file change cost 15 second (for type checking)?
There was a problem hiding this comment.
It's closer to 5 seconds for updates. The initial 15 seconds is for the first build and is slower because all of the compile tasks are running at the same time
There was a problem hiding this comment.
I've now also enabled the --incremental option to speed up recompiles. In my testing, this reduces the recheck time to 2seconds. Hopefully longer term the TS team will improve their watcher so that we can use that and speed this up even further
| const ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; | ||
| const timestampRegex = /^\[\d{2}:\d{2}:\d{2}\]\s*/; | ||
|
|
||
| export function spawnTsgo(projectPath: string, config: { taskName: string; noEmit?: boolean }, onComplete?: () => Promise<void> | void): Promise<void> { |
There was a problem hiding this comment.
This should probably replace what I have added for CI/CD here
vscode/build/gulpfile.vscode.ts
Line 219 in 7ffca95
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This reduces the the first run time to get
srctranspiled and fully type checked to around 15seconds on my machine. Rechecking then takes around 5 seconds