diff --git a/packages/vite/package.json b/packages/vite/package.json index e6e5e3e850c2c9..f4f254bb6b1c22 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -113,7 +113,7 @@ "source-map-support": "^0.5.21", "strip-ansi": "^6.0.1", "terser": "^5.10.0", - "tsconfck": "1.1.2", + "tsconfck": "^1.2.0", "tslib": "^2.3.1", "types": "link:./types", "ws": "^8.5.0" diff --git a/packages/vite/src/node/plugins/esbuild.ts b/packages/vite/src/node/plugins/esbuild.ts index e0a7f884e000be..f0e25945828f49 100644 --- a/packages/vite/src/node/plugins/esbuild.ts +++ b/packages/vite/src/node/plugins/esbuild.ts @@ -20,8 +20,9 @@ import type { SourceMap } from 'rollup' import type { ResolvedConfig, ViteDevServer } from '..' import { createFilter } from '@rollup/pluginutils' import { combineSourcemaps } from '../utils' -import type { TSConfckParseResult } from 'tsconfck' -import { parse, TSConfckParseError } from 'tsconfck' +import type { TSConfckParseOptions, TSConfckParseResult } from 'tsconfck' +import { parse, findAll, TSConfckParseError } from 'tsconfck' +import { searchForWorkspaceRoot } from '..' const debug = createDebugger('vite:esbuild') @@ -179,6 +180,9 @@ export function esbuildPlugin(options: ESBuildOptions = {}): Plugin { .on('change', reloadOnTsconfigChange) .on('unlink', reloadOnTsconfigChange) }, + async configResolved(config) { + await initTSConfck(config) + }, buildEnd() { // recycle serve to avoid preventing Node self-exit (#6815) server = null as any @@ -224,6 +228,9 @@ const rollupToEsbuildFormatMap: Record< export const buildEsbuildPlugin = (config: ResolvedConfig): Plugin => { return { name: 'vite:esbuild-transpile', + async configResolved(config) { + await initTSConfck(config) + }, async renderChunk(code, chunk, opts) { // @ts-ignore injected by @vitejs/plugin-legacy if (opts.__vite_skip_esbuild__) { @@ -274,15 +281,29 @@ function prettifyMessage(m: Message, code: string): string { return res + `\n` } -const tsconfigCache = new Map() +const tsconfckParseOptions: TSConfckParseOptions = { + cache: new Map(), + tsConfigPaths: undefined, + root: undefined, + resolveWithEmptyIfConfigNotFound: true +} + +async function initTSConfck(config: ResolvedConfig) { + tsconfckParseOptions.cache!.clear() + const workspaceRoot = searchForWorkspaceRoot(config.root) + tsconfckParseOptions.root = workspaceRoot + tsconfckParseOptions.tsConfigPaths = new Set([ + ...(await findAll(workspaceRoot, { + skip: (dir) => dir === 'node_modules' || dir === '.git' + })) + ]) +} + async function loadTsconfigJsonForFile( filename: string ): Promise { try { - const result = await parse(filename, { - cache: tsconfigCache, - resolveWithEmptyIfConfigNotFound: true - }) + const result = await parse(filename, tsconfckParseOptions) // tsconfig could be out of root, make sure it is watched on dev if (server && result.tsconfigFile !== 'no_tsconfig_file_found') { ensureWatchedFile(server.watcher, result.tsconfigFile, server.config.root) @@ -304,20 +325,24 @@ function reloadOnTsconfigChange(changedFile: string) { // any json file in the tsconfig cache could have been used to compile ts if ( path.basename(changedFile) === 'tsconfig.json' || - (changedFile.endsWith('.json') && tsconfigCache.has(changedFile)) + (changedFile.endsWith('.json') && + tsconfckParseOptions?.cache?.has(changedFile)) ) { server.config.logger.info( `changed tsconfig file detected: ${changedFile} - Clearing cache and forcing full-reload to ensure typescript is compiled with updated config values.`, { clear: server.config.clearScreen, timestamp: true } ) - // clear tsconfig cache so that recompile works with up2date configs - tsconfigCache.clear() + // clear module graph to remove code compiled with outdated config server.moduleGraph.invalidateAll() - // force full reload - server.ws.send({ - type: 'full-reload', - path: '*' + + // reset tsconfck so that recompile works with up2date configs + initTSConfck(server.config).finally(() => { + // force full reload + server.ws.send({ + type: 'full-reload', + path: '*' + }) }) } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ab2b4a7833c686..736f012b037db6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -803,7 +803,7 @@ importers: source-map-support: ^0.5.21 strip-ansi: ^6.0.1 terser: ^5.10.0 - tsconfck: 1.1.2 + tsconfck: ^1.2.0 tslib: ^2.3.1 types: link:./types ws: ^8.5.0 @@ -876,7 +876,7 @@ importers: source-map-support: 0.5.21 strip-ansi: 6.0.1 terser: 5.10.0_acorn@8.7.0 - tsconfck: 1.1.2_typescript@4.5.4 + tsconfck: 1.2.0_typescript@4.5.4 tslib: 2.3.1 types: link:types ws: 8.5.0 @@ -3103,7 +3103,7 @@ packages: resolution: {integrity: sha512-oagLNqpfNv7CvmyMoexMDNyVDSiq1rya0AEUgcLlNHdHgNl6U/hi8xY370n5y+ZIFEXOx0J4B1qF2NDjMRxklA==} engines: {node: '>=6.0.0'} dependencies: - pvutils: 1.0.17 + pvutils: 1.1.2 dev: true /assert-never/1.2.1: @@ -7690,8 +7690,8 @@ packages: tslib: 2.3.1 dev: true - /pvutils/1.0.17: - resolution: {integrity: sha512-wLHYUQxWaXVQvKnwIDWFVKDJku9XDCvyhhxoq8dc5MFdIlRenyPI9eSfEtcvgHgD7FlvCyGAlWgOzRnZD99GZQ==} + /pvutils/1.1.2: + resolution: {integrity: sha512-wlo0BUInyP+ZgBJHV8PnJW8S2HubdQfMMip8B9yXr9aFlauJFuF1jZ/RWFmzGYitC7GxkxqXdwbY9/R97v+Cqg==} engines: {node: '>=6.0.0'} dev: true @@ -8916,8 +8916,8 @@ packages: yn: 3.1.1 dev: true - /tsconfck/1.1.2_typescript@4.5.4: - resolution: {integrity: sha512-n6SkiUQ784Uu2pviyd0j2kspm/fipdjO5jZuR8zUHVVoQeRnR6BSV5zlbheDmpyP0lj7GvHWvFcaxxhUFrzQWQ==} + /tsconfck/1.2.0_typescript@4.5.4: + resolution: {integrity: sha512-uKBM6x6i5e7Tfof5Zhll2ypgYKwWZhsxsHOoCH/7enlcHjjlcZ8FnxFrqgVFtpN6ymzZX3zoDaVGIlkh/g4x6w==} engines: {node: ^12.20 || ^14.13.1 || >= 16} hasBin: true peerDependencies: