From 0bdaeb486fd0834aa95dd90a5649863daed80842 Mon Sep 17 00:00:00 2001 From: Sakana <15715093608@163.com> Date: Wed, 7 Oct 2026 14:16:07 +0800 Subject: [PATCH 1/2] fix(vite): include declined loads in module timings Keep load calls without code results in separate timing records tied to the request that produces the module snapshot. Clear pending records when requests finish or modules invalidate. Preserve request identity through batched writes and replace stale code snapshots on native file-read retries so failed attempts do not pollute successful loads. --- .../node/__tests__/inspect-context.test.ts | 126 +++++++++++++++ .../src/node/__tests__/inspect-server.test.ts | 153 ++++++++++++++++++ packages/vite/src/node/inspect/context.ts | 7 +- packages/vite/src/node/inspect/module.ts | 11 +- packages/vite/src/node/inspect/server.ts | 2 + packages/vite/src/node/inspect/store/index.ts | 116 ++++++++++--- packages/vite/src/node/inspect/store/types.ts | 17 ++ 7 files changed, 408 insertions(+), 24 deletions(-) diff --git a/packages/vite/src/node/__tests__/inspect-context.test.ts b/packages/vite/src/node/__tests__/inspect-context.test.ts index 9c863e8dd..1328be46f 100644 --- a/packages/vite/src/node/__tests__/inspect-context.test.ts +++ b/packages/vite/src/node/__tests__/inspect-context.test.ts @@ -1030,4 +1030,130 @@ describe('vite inspect context', () => { ], }) }) + it.each(['memory', 'disk'])('counts declined loads without replacing code (%s)', async (storage) => { + const dir = mkdtempSync(join(tmpdir(), 'vite-load-timing-')) + const { ctx, envCtx, vite } = await createFixture({ store: { filename: storage === 'disk' ? join(dir, 'payloads.bin') : ':memory:', maxBatchItems: 1 } }) + try { + const id = '/src/load-timing.ts' + const source = 'export const value = 1' + const record = () => { + envCtx.recordLoadCall(id, { name: 'plugin-a', start: 0, end: 200 }, vite.config.plugins[1]) + envCtx.recordLoad(id, { name: 'vite:load-fallback', result: source, start: 200, end: 202 }, vite.config.plugins[0]) + envCtx.recordTransform(id, { name: 'plugin-b', result: source, start: 202, end: 205 }, source, vite.config.plugins[2]) + } + record() + const assertMetrics = async (calls = 1) => { + const [module] = await envCtx.getModulesList() + expect(module).toMatchObject({ totalTime: 205, virtual: false, sourceSize: source.length, distSize: source.length }) + expect(module!.plugins).toContainEqual({ name: 'plugin-a', transform: 200 }) + expect((await envCtx.getModuleTransformInfo(id)).transforms.map(t => t.name)).toEqual(['vite:load-fallback', 'plugin-b']) + expect((await envCtx.getPluginDetails(1)).loadMetrics).toHaveLength(calls) + } + await assertMetrics() + record() + await assertMetrics(2) + envCtx.invalidate(id) + expect(await envCtx.getModulesList()).toEqual([]) + record() + await assertMetrics() + envCtx.clearScope() + expect(await envCtx.getModulesList()).toEqual([]) + } + finally { + await ctx.close() + rmSync(dir, { recursive: true, force: true }) + } + }) + + it.each(['memory', 'disk'])('isolates overlapping load requests (%s)', async (storage) => { + const dir = mkdtempSync(join(tmpdir(), 'vite-load-requests-')) + const { ctx, envCtx } = await createFixture({ store: { + filename: storage === 'disk' ? join(dir, 'payloads.bin') : ':memory:', + maxBatchItems: storage === 'disk' ? 1 : undefined, + } }) + try { + const id = '/src/load-requests.ts' + const source = 'export const value = 1' + const failedRequest = {} + const successfulRequest = {} + const recordCall = (request: object, duration: number) => { + ctx.store.recordPluginCall(envCtx.scope, { + type: 'load', + id: `load:${duration}`, + duration, + plugin_id: 1, + plugin_name: 'plugin-a', + module: id, + timestamp_start: 0, + timestamp_end: duration, + unchanged: true, + }, request) + } + recordCall(failedRequest, 100) + recordCall(successfulRequest, 20) + ctx.store.finishLoadRequest(envCtx.scope, failedRequest) + ctx.store.recordLoad(envCtx.scope, id, id, { + name: 'vite:load-fallback', + result: source, + start: 20, + end: 22, + }, undefined, successfulRequest) + ctx.store.finishLoadRequest(envCtx.scope, successfulRequest) + + const [module] = await envCtx.getModulesList() + expect(module).toMatchObject({ totalTime: 22, sourceSize: source.length, distSize: source.length }) + expect(module!.plugins).toContainEqual({ name: 'plugin-a', transform: 20 }) + expect((await envCtx.getPluginDetails(1)).loadMetrics).toHaveLength(2) + } + finally { + await ctx.close() + rmSync(dir, { recursive: true, force: true }) + } + }) + + it.each(['memory', 'disk'])('replaces a previous request source within a write batch (%s)', async (storage) => { + const dir = mkdtempSync(join(tmpdir(), 'vite-source-retry-')) + const { ctx, envCtx } = await createFixture({ store: { + filename: storage === 'disk' ? join(dir, 'payloads.bin') : ':memory:', + } }) + try { + const id = '/src/source-retry.ts' + const source = 'export const value = 1' + const output = 'export const value = 2' + const failedRequest = {} + const successfulRequest = {} + ctx.store.recordLoad(envCtx.scope, id, id, { + name: 'failed-load', + result: '[Error]', + start: 0, + end: 80, + }, undefined, failedRequest) + ctx.store.recordTransform(envCtx.scope, id, id, { + name: 'plugin-a', + start: 80, + end: 83, + }, source, undefined, successfulRequest) + ctx.store.recordTransform(envCtx.scope, id, id, { + name: 'plugin-b', + result: output, + start: 83, + end: 85, + }, source, undefined, successfulRequest) + ctx.store.finishLoadRequest(envCtx.scope, failedRequest) + ctx.store.finishLoadRequest(envCtx.scope, successfulRequest) + + expect((await envCtx.getModuleTransformInfo(id)).transforms).toMatchObject([ + { name: '__load__', result: source }, + { name: 'plugin-a' }, + { name: 'plugin-b', result: output }, + ]) + expect(await envCtx.getModulesList()).toMatchObject([ + { id, sourceSize: source.length, distSize: output.length, invokeCount: 2 }, + ]) + } + finally { + await ctx.close() + rmSync(dir, { recursive: true, force: true }) + } + }) }) diff --git a/packages/vite/src/node/__tests__/inspect-server.test.ts b/packages/vite/src/node/__tests__/inspect-server.test.ts index d4b5dc7c9..3158025b9 100644 --- a/packages/vite/src/node/__tests__/inspect-server.test.ts +++ b/packages/vite/src/node/__tests__/inspect-server.test.ts @@ -1,6 +1,9 @@ import type { Environment, Plugin, ViteDevServer } from 'vite' import type { ViteInspectEnvironmentContext } from '../inspect/context' import type { ViteInspectStoreOptions } from '../inspect/store' +import { mkdtempSync, realpathSync, rmSync, writeFileSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { join } from 'node:path' import { createServer } from 'vite' import { afterEach, describe, expect, it, vi } from 'vitest' import { ViteInspectContext } from '../inspect/context' @@ -15,12 +18,15 @@ interface InspectServerFixture { } const fixtures: InspectServerFixture[] = [] +const temporaryDirs: string[] = [] afterEach(async () => { await Promise.all(fixtures.splice(0).map(async ({ server, inspectContext }) => { await server.close() await inspectContext.close() })) + for (const dir of temporaryDirs.splice(0)) + rmSync(dir, { recursive: true, force: true }) }) async function createInspectServer( @@ -332,4 +338,151 @@ describe('vite inspect server invalidation', () => { expect(lateRequest).toBeUndefined() }) + it.each(['memory', 'disk'])('excludes failed loads from a successful retry (%s)', async (storage) => { + const dir = mkdtempSync(join(tmpdir(), 'vite-load-retry-')) + temporaryDirs.push(dir) + const id = '/load-retry.js' + const source = 'export const value = 1' + let enabled = false + const plugin: Plugin = { + name: 'test:retry-load', + enforce: 'pre', + async load(moduleId) { + if (moduleId !== id) + return + await new Promise(resolve => setTimeout(resolve, 20)) + }, + } + const provider: Plugin = { + name: 'test:retry-provider', + resolveId(moduleId) { + if (moduleId === id) + return id + }, + load(moduleId) { + if (moduleId === id && enabled) + return source + }, + } + const { server, envContext } = await createInspectServer(new Map(), [plugin, provider], { + filename: storage === 'disk' ? join(dir, 'payloads.bin') : ':memory:', + maxBatchItems: storage === 'disk' ? 1 : undefined, + }) + await expect(server.transformRequest(id)).rejects.toThrow() + enabled = true + await server.transformRequest(id) + + const details = await envContext.getPluginDetails(server.config.plugins.indexOf(plugin)) + expect(details.loadMetrics).toHaveLength(2) + expect(details.loadMetrics[0]!.duration).toBeGreaterThan(0) + const duration = details.loadMetrics[1]!.duration + expect(duration).toBeGreaterThan(0) + const module = (await envContext.getModulesList()).find(module => module.id === id)! + expect(module.plugins.filter(p => p.name === plugin.name)).toEqual([{ name: plugin.name, transform: duration }]) + expect(module.sourceSize).toBe(source.length) + expect((await envContext.getModuleTransformInfo(id)).transforms[0]?.result).toBe(source) + }) + + it.each(['memory', 'disk'])('replaces failed load timings when a retry reads a file (%s)', async (storage) => { + const dir = realpathSync(mkdtempSync(join(tmpdir(), 'vite-file-load-retry-'))) + temporaryDirs.push(dir) + const id = join(dir, 'entry.js').replace(/\\/g, '/') + const source = 'export const value = 1' + writeFileSync(id, source) + let fail = true + let now = Date.now() + const clock = vi.spyOn(Date, 'now').mockImplementation(() => now) + const declined: Plugin = { + name: 'test:declined-file-load', + enforce: 'pre', + load(moduleId) { + if (moduleId === id) + now += fail ? 80 : 5 + }, + } + const failing: Plugin = { + name: 'test:failing-file-load', + enforce: 'pre', + load(moduleId) { + if (moduleId === id && fail) + this.error('First load attempt failed') + }, + } + try { + const { server, envContext } = await createInspectServer(new Map(), [declined, failing], { + filename: storage === 'disk' ? join(dir, 'payloads.bin') : ':memory:', + maxBatchItems: storage === 'disk' ? 1 : undefined, + }) + await expect(server.transformRequest(id)).rejects.toThrow('First load attempt failed') + // Persist the failed snapshot before the retry starts. + await envContext.getModulesList() + fail = false + await server.transformRequest(id) + + const details = await envContext.getPluginDetails(server.config.plugins.indexOf(declined)) + expect(details.loadMetrics.map(call => call.duration)).toEqual([80, 5]) + const module = (await envContext.getModulesList()).find(module => module.id === id)! + expect(module.plugins.filter(plugin => plugin.name === declined.name)).toEqual([ + { name: declined.name, transform: 5 }, + ]) + expect(module).toMatchObject({ sourceSize: source.length, distSize: source.length, virtual: false }) + const { transforms } = await envContext.getModuleTransformInfo(id) + expect(transforms[0]).toMatchObject({ name: '__load__', result: source }) + expect(transforms.some(transform => transform.result === '[Error]')).toBe(false) + } + finally { + clock.mockRestore() + } + }) + + it.each([undefined, null, 'code'] as const)('counts load time with result %s through Vite', async (result) => { + const id = '/load-timing.js' + const source = 'export const value = 1' + const plugin: Plugin = { + name: 'test:slow-load', + enforce: 'pre', + async load(moduleId) { + if (moduleId !== id) + return + await new Promise(resolve => setTimeout(resolve, 20)) + return result === 'code' ? source : result + }, + } + const { server, envContext } = await createInspectServer(new Map([[id, source]]), [plugin]) + await server.transformRequest(id) + const details = await envContext.getPluginDetails(server.config.plugins.indexOf(plugin)) + const duration = details.loadMetrics.reduce((sum, call) => sum + call.duration, 0) + expect(duration).toBeGreaterThan(0) + const [module] = await envContext.getModulesList() + expect(module!.plugins.filter(p => p.name === plugin.name).reduce((sum, p) => sum + (p.transform ?? 0), 0)).toBe(duration) + expect(module!.sourceSize).toBe(source.length) + expect(module!.distSize).toBe(source.length) + }) + + it.each([undefined, null])('counts declined loads before Vite reads a file (%s)', async (result) => { + const dir = realpathSync(mkdtempSync(join(tmpdir(), 'vite-file-load-'))) + temporaryDirs.push(dir) + const id = join(dir, 'entry.js').replace(/\\/g, '/') + const source = 'export const value = 1' + writeFileSync(id, source) + const plugin: Plugin = { + name: 'test:declined-file-load', + enforce: 'pre', + async load(moduleId) { + if (moduleId !== id) + return + await new Promise(resolve => setTimeout(resolve, 20)) + return result + }, + } + const { server, envContext } = await createInspectServer(new Map(), [plugin]) + await server.transformRequest(id) + const details = await envContext.getPluginDetails(server.config.plugins.indexOf(plugin)) + const duration = details.loadMetrics.reduce((sum, call) => sum + call.duration, 0) + expect(duration).toBeGreaterThan(0) + const [module] = await envContext.getModulesList() + expect(module!.plugins).toContainEqual({ name: plugin.name, transform: duration }) + expect(module!.sourceSize).toBe(source.length) + expect(module!.virtual).toBe(false) + }) }) diff --git a/packages/vite/src/node/inspect/context.ts b/packages/vite/src/node/inspect/context.ts index 2110a7634..588e10b8f 100644 --- a/packages/vite/src/node/inspect/context.ts +++ b/packages/vite/src/node/inspect/context.ts @@ -32,6 +32,7 @@ import { getPluginDetails as getEnvironmentPluginDetails, getPluginMetrics as getEnvironmentPluginMetrics, } from './plugins' +import { trackTransformRequestId } from './server' import { createViteInspectStore } from './store' import { normalizeModuleId, @@ -215,7 +216,7 @@ export class ViteInspectEnvironmentContext { this.inspectContext.store.recordTransform(this.scope, id, publicModuleId, { ...info, plugin_id: pluginId, - }, preTransformCode, pluginCall) + }, preTransformCode, pluginCall, trackTransformRequestId(id)) } recordLoad( @@ -240,7 +241,7 @@ export class ViteInspectEnvironmentContext { this.inspectContext.store.recordLoad(this.scope, id, publicModuleId, { ...info, plugin_id: pluginId, - }, pluginCall) + }, pluginCall, trackTransformRequestId(id)) } recordLoadCall( @@ -262,7 +263,7 @@ export class ViteInspectEnvironmentContext { if (!pluginCall) return - this.inspectContext.store.recordPluginCall(this.scope, pluginCall) + this.inspectContext.store.recordPluginCall(this.scope, pluginCall, trackTransformRequestId(id)) } recordResolveId( diff --git a/packages/vite/src/node/inspect/module.ts b/packages/vite/src/node/inspect/module.ts index 4b1d45b2f..b9cf126a0 100644 --- a/packages/vite/src/node/inspect/module.ts +++ b/packages/vite/src/node/inspect/module.ts @@ -31,6 +31,13 @@ export async function getModulesList( const transformList = await ctx.inspectContext.store.getTransformList(ctx.scope) const resolveIdList = await ctx.inspectContext.store.getResolveIdList(ctx.scope) + const declinedLoads = await ctx.inspectContext.store.getDeclinedLoadMetrics(ctx.scope) + const declinedLoadsById = new Map() + for (const load of declinedLoads) { + const plugins = declinedLoadsById.get(load.publicModuleId) ?? [] + plugins.push({ name: load.pluginName, transform: load.totalTime }) + declinedLoadsById.set(load.publicModuleId, plugins) + } const transformsById = transformList.reduce>((map, transform) => { const transforms = map[transform.moduleId] ||= [] @@ -63,7 +70,9 @@ export async function getModulesList( name: resolveId.name, resolveId: resolveId.end - resolveId.start, })) - const plugins = transformPlugins.concat(resolveIdPlugins) + const loadPlugins = declinedLoadsById.get(ctx.getPublicModuleId(id)) ?? [] + totalTime += loadPlugins.reduce((sum, plugin) => sum + (plugin.transform ?? 0), 0) + const plugins = transformPlugins.concat(loadPlugins, resolveIdPlugins) const firstTransform = transforms[0] const lastTransform = transforms.at(-1) diff --git a/packages/vite/src/node/inspect/server.ts b/packages/vite/src/node/inspect/server.ts index a777945c5..2f5e7debf 100644 --- a/packages/vite/src/node/inspect/server.ts +++ b/packages/vite/src/node/inspect/server.ts @@ -64,6 +64,8 @@ export function setupEnvironmentInvalidation(server: ViteDevServer, vite: ViteIn state.activeRequests.add(request) return transformRequestStorage.run(request, () => transformRequest.apply(this, args)) .finally(() => { + for (const context of state.contexts) + context.inspectContext.store.finishLoadRequest(context.scope, request) request.active = false request.ids.clear() state.activeRequests.delete(request) diff --git a/packages/vite/src/node/inspect/store/index.ts b/packages/vite/src/node/inspect/store/index.ts index 803050add..a3b85e54c 100644 --- a/packages/vite/src/node/inspect/store/index.ts +++ b/packages/vite/src/node/inspect/store/index.ts @@ -12,6 +12,7 @@ import type { PendingWrite, QueuedWrite, StoredViteInspectTransformInfo, + ViteInspectModuleLoadMetric, ViteInspectPayloadRange, ViteInspectPluginMetricItem, ViteInspectResolveIdItem, @@ -31,6 +32,7 @@ const DEFAULT_MAX_BATCH_ITEMS = 256 const DEFAULT_MAX_BATCH_BYTES = 8 * 1024 * 1024 interface StoredModuleTransforms { + loadRequest?: object publicModuleId: string invokeCount: number items: StoredViteInspectTransformInfo[] @@ -39,10 +41,12 @@ interface StoredModuleTransforms { interface ScopeData { transforms: Map resolveIds: Map + declinedLoads: Map> + pendingLoads: Map>> } interface PreparedWrite { - write: Exclude + write: Exclude resultIndex?: number sourceIndex?: number sourcemapIndex?: number @@ -121,6 +125,7 @@ class PayloadViteInspectStore implements ViteInspectStore { info: ViteInspectTransformInfo, preTransformCode: string, pluginCall?: ViteInspectPluginCallInfo, + loadRequest?: object, ): void { this.enqueue({ operation: 'recordTransform', @@ -130,6 +135,7 @@ class PayloadViteInspectStore implements ViteInspectStore { info, preTransformCode, pluginCall, + loadRequest, }) } @@ -139,6 +145,7 @@ class PayloadViteInspectStore implements ViteInspectStore { publicModuleId: string, info: ViteInspectTransformInfo, pluginCall?: ViteInspectPluginCallInfo, + loadRequest?: object, ): void { this.enqueue({ operation: 'recordLoad', @@ -147,6 +154,7 @@ class PayloadViteInspectStore implements ViteInspectStore { publicModuleId, info, pluginCall, + loadRequest, }) } @@ -169,14 +177,19 @@ class PayloadViteInspectStore implements ViteInspectStore { }) } - recordPluginCall(scope: string, info: ViteInspectPluginCallInfo): void { + recordPluginCall(scope: string, info: ViteInspectPluginCallInfo, loadRequest?: object): void { this.enqueue({ operation: 'recordPluginCall', scope, info, + loadRequest, }) } + finishLoadRequest(scope: string, loadRequest: object): void { + this.enqueue({ operation: 'finishLoadRequest', scope, loadRequest }) + } + invalidate(scope: string, moduleId: string, publicModuleId: string): void { this.enqueue({ operation: 'invalidate', @@ -214,6 +227,13 @@ class PayloadViteInspectStore implements ViteInspectStore { return result } + async getDeclinedLoadMetrics(scope: string): Promise { + await this.flush() + return Array.from(this.scopes.get(scope)?.declinedLoads ?? []).flatMap(([publicModuleId, metrics]) => + Array.from(metrics.values(), metric => ({ ...metric, publicModuleId })), + ) + } + async getResolveIdList(scope: string): Promise { await this.flush() return Array.from(this.scopes.get(scope)?.resolveIds.values() ?? []).flat() @@ -401,7 +421,7 @@ class PayloadViteInspectStore implements ViteInspectStore { } private async writeBatch(batch: PendingWrite[]): Promise { - let dataWrites: Array> = [] + let dataWrites: Array> = [] const flushDataWrites = async () => { if (dataWrites.length === 0) return @@ -415,6 +435,10 @@ class PayloadViteInspectStore implements ViteInspectStore { await flushDataWrites() this.invalidateNow(write.scope, write.moduleId, write.publicModuleId) } + else if (write.operation === 'finishLoadRequest') { + await flushDataWrites() + this.scopes.get(write.scope)?.pendingLoads.delete(write.loadRequest) + } else if (write.operation === 'clearScope') { await flushDataWrites() this.clearScopeNow(write.scope) @@ -427,21 +451,25 @@ class PayloadViteInspectStore implements ViteInspectStore { } private async writeDataBatch( - writes: Array>, + writes: Array>, ): Promise { const values: Array = [] const prepared: PreparedWrite[] = [] const pluginCallWrites: InspectPluginCallWrite[] = [] - const sourceState = new Map() + const sourceState = new Map() - const hasSource = (scope: string, moduleId: string): boolean => { + const hasSource = (scope: string, moduleId: string, loadRequest?: object): boolean => { const key = scopeKey(scope, moduleId) - const pending = sourceState.get(key) - if (pending != null) - return pending - const stored = this.scopes.get(scope)?.transforms.get(moduleId)?.items.some(item => item.hasResult) ?? false - sourceState.set(key, stored) - return stored + let state = sourceState.get(key) + if (!state) { + const stored = this.scopes.get(scope)?.transforms.get(moduleId) + state = { + hasSource: stored?.items.some(item => item.hasResult) ?? false, + loadRequest: stored?.loadRequest, + } + sourceState.set(key, state) + } + return state.hasSource && (!loadRequest || state.loadRequest === loadRequest) } for (const write of writes) { @@ -452,15 +480,15 @@ class PayloadViteInspectStore implements ViteInspectStore { info: pluginCall, }) } - if (write.operation === 'recordPluginCall') + if (write.operation === 'recordPluginCall' && write.info.type !== 'load') continue const item: PreparedWrite = { write } if (write.operation === 'recordTransform') { const key = scopeKey(write.scope, write.moduleId) - if (!hasSource(write.scope, write.moduleId)) { + if (!hasSource(write.scope, write.moduleId, write.loadRequest)) { item.sourceIndex = values.push(write.preTransformCode) - 1 - sourceState.set(key, true) + sourceState.set(key, { hasSource: true, loadRequest: write.loadRequest }) } item.resultIndex = values.push(write.info.result) - 1 item.sourcemapIndex = pushSerializedPayload(values, write.info.sourcemaps) @@ -468,7 +496,7 @@ class PayloadViteInspectStore implements ViteInspectStore { else if (write.operation === 'recordLoad') { item.resultIndex = values.push(write.info.result) - 1 item.sourcemapIndex = pushSerializedPayload(values, write.info.sourcemaps) - sourceState.set(scopeKey(write.scope, write.moduleId), write.info.result != null) + sourceState.set(scopeKey(write.scope, write.moduleId), { hasSource: write.info.result != null, loadRequest: write.loadRequest }) } prepared.push(item) } @@ -501,6 +529,21 @@ class PayloadViteInspectStore implements ViteInspectStore { rangeAt(ranges, prepared.sourcemapIndex), ) } + else if (write.operation === 'recordPluginCall' && write.info.type === 'load') { + // Declined loads have timing data but must not replace the module's code. + const data = this.getScope(write.scope) + let pendingLoads = data.pendingLoads.get(write.loadRequest) + if (!pendingLoads) { + pendingLoads = new Map() + data.pendingLoads.set(write.loadRequest, pendingLoads) + } + let metrics = pendingLoads.get(write.info.module) + if (!metrics) { + metrics = new Map() + pendingLoads.set(write.info.module, metrics) + } + addMetric(metrics, write.info.plugin_id, write.info.plugin_name, write.info.duration) + } else if (write.operation === 'recordResolveId') { const data = this.getScope(write.scope) let resolveIds = data.resolveIds.get(write.sourceId) @@ -529,16 +572,23 @@ class PayloadViteInspectStore implements ViteInspectStore { ): void { const data = this.getScope(write.scope) let transforms = data.transforms.get(write.moduleId) - if (!transforms) { + // A new request can reach transform through Vite's direct file read. + // Replace the previous snapshot even when it contains a load error result. + if (!transforms || (write.loadRequest && transforms.loadRequest !== write.loadRequest)) { + if (transforms) + this.payloads.reclaim(collectPayloadRanges(transforms.items)) transforms = { + loadRequest: write.loadRequest, publicModuleId: write.publicModuleId, - invokeCount: 0, + invokeCount: transforms?.invokeCount ?? 0, items: [], } data.transforms.set(write.moduleId, transforms) } if (!transforms.items.some(item => item.hasResult)) { + // Vite can read files itself without a successful load hook. + this.commitLoadMetrics(data, write.publicModuleId, write.loadRequest) transforms.items.push({ name: DUMMY_LOAD_PLUGIN_NAME, hasResult: true, @@ -559,16 +609,31 @@ class PayloadViteInspectStore implements ViteInspectStore { sourcemaps: ViteInspectPayloadRange | undefined, ): void { const data = this.getScope(write.scope) + this.commitLoadMetrics(data, write.publicModuleId, write.loadRequest) const existing = data.transforms.get(write.moduleId) if (existing) this.payloads.reclaim(collectPayloadRanges(existing.items)) data.transforms.set(write.moduleId, { + loadRequest: write.loadRequest, publicModuleId: write.publicModuleId, invokeCount: (existing?.invokeCount ?? 0) + 1, items: [toStoredTransformInfo(write.info, result, sourcemaps)], }) } + private commitLoadMetrics(data: ScopeData, publicModuleId: string, loadRequest?: object): void { + // Only this request can contribute declined loads to its code snapshot. + const pendingLoads = data.pendingLoads.get(loadRequest) + const declinedLoads = pendingLoads?.get(publicModuleId) + if (declinedLoads) + data.declinedLoads.set(publicModuleId, declinedLoads) + else + data.declinedLoads.delete(publicModuleId) + pendingLoads?.delete(publicModuleId) + if (pendingLoads?.size === 0) + data.pendingLoads.delete(loadRequest) + } + private invalidateNow(scope: string, moduleId: string, publicModuleId: string): void { const data = this.scopes.get(scope) if (!data) { @@ -617,6 +682,15 @@ class PayloadViteInspectStore implements ViteInspectStore { data.resolveIds.delete(sourceId) } + for (const id of invalidPublicIds) { + data.declinedLoads.delete(id) + for (const [request, pendingLoads] of data.pendingLoads) { + pendingLoads.delete(id) + if (pendingLoads.size === 0) + data.pendingLoads.delete(request) + } + } + this.pluginCalls.invalidate(scope, invalidPublicIds) } @@ -680,6 +754,8 @@ class PayloadViteInspectStore implements ViteInspectStore { data = { transforms: new Map(), resolveIds: new Map(), + declinedLoads: new Map(), + pendingLoads: new Map(), } this.scopes.set(scope, data) } @@ -852,7 +928,7 @@ function positiveInteger(value: number | undefined, fallback: number): number { } function estimateWriteBytes(write: QueuedWrite): number { - const pluginCall = write.operation === 'invalidate' || write.operation === 'clearScope' + const pluginCall = write.operation === 'invalidate' || write.operation === 'clearScope' || write.operation === 'finishLoadRequest' ? undefined : getQueuedPluginCall(write) const pluginCallBytes = pluginCall @@ -876,7 +952,7 @@ function estimateWriteBytes(write: QueuedWrite): number { } function getQueuedPluginCall( - write: Exclude, + write: Exclude, ): ViteInspectPluginCallInfo | undefined { return write.operation === 'recordPluginCall' ? write.info : write.pluginCall } diff --git a/packages/vite/src/node/inspect/store/types.ts b/packages/vite/src/node/inspect/store/types.ts index d1d8d6493..4027cd52b 100644 --- a/packages/vite/src/node/inspect/store/types.ts +++ b/packages/vite/src/node/inspect/store/types.ts @@ -70,6 +70,10 @@ export interface ViteInspectPluginMetricItem { totalTime: number } +export interface ViteInspectModuleLoadMetric extends ViteInspectPluginMetricItem { + publicModuleId: string +} + export interface ViteInspectStore { recordTransform: ( scope: string, @@ -78,6 +82,7 @@ export interface ViteInspectStore { info: ViteInspectTransformInfo, preTransformCode: string, pluginCall?: ViteInspectPluginCallInfo, + loadRequest?: object, ) => void recordLoad: ( scope: string, @@ -85,6 +90,7 @@ export interface ViteInspectStore { publicModuleId: string, info: ViteInspectTransformInfo, pluginCall?: ViteInspectPluginCallInfo, + loadRequest?: object, ) => void recordResolveId: ( scope: string, @@ -97,10 +103,13 @@ export interface ViteInspectStore { recordPluginCall: ( scope: string, info: ViteInspectPluginCallInfo, + loadRequest?: object, ) => void + finishLoadRequest: (scope: string, loadRequest: object) => void invalidate: (scope: string, moduleId: string, publicModuleId: string) => void clearScope: (scope: string) => void getTransformList: (scope: string) => Promise + getDeclinedLoadMetrics: (scope: string) => Promise getResolveIdList: (scope: string) => Promise getPluginTransformMetrics: (scope: string) => Promise getPluginResolveIdMetrics: (scope: string) => Promise @@ -123,6 +132,7 @@ export type QueuedWrite info: ViteInspectTransformInfo preTransformCode: string pluginCall?: ViteInspectPluginCallInfo + loadRequest?: object } | { operation: 'recordLoad' @@ -131,6 +141,7 @@ export type QueuedWrite publicModuleId: string info: ViteInspectTransformInfo pluginCall?: ViteInspectPluginCallInfo + loadRequest?: object } | { operation: 'recordResolveId' @@ -145,6 +156,12 @@ export type QueuedWrite operation: 'recordPluginCall' scope: string info: ViteInspectPluginCallInfo + loadRequest?: object + } + | { + operation: 'finishLoadRequest' + scope: string + loadRequest: object } | { operation: 'invalidate' From e13d83753cb87400dd1cf6d8bde1dc30ba8baaf8 Mon Sep 17 00:00:00 2001 From: arlo Date: Fri, 9 Oct 2026 21:17:01 +0800 Subject: [PATCH 2/2] chore: improve naming --- .../node/__tests__/inspect-context.test.ts | 8 +- packages/vite/src/node/inspect/module.ts | 12 +- packages/vite/src/node/inspect/server.ts | 2 +- packages/vite/src/node/inspect/store/index.ts | 110 +++++++++--------- packages/vite/src/node/inspect/store/types.ts | 22 ++-- 5 files changed, 77 insertions(+), 77 deletions(-) diff --git a/packages/vite/src/node/__tests__/inspect-context.test.ts b/packages/vite/src/node/__tests__/inspect-context.test.ts index 1328be46f..9f37eb8bd 100644 --- a/packages/vite/src/node/__tests__/inspect-context.test.ts +++ b/packages/vite/src/node/__tests__/inspect-context.test.ts @@ -1091,14 +1091,14 @@ describe('vite inspect context', () => { } recordCall(failedRequest, 100) recordCall(successfulRequest, 20) - ctx.store.finishLoadRequest(envCtx.scope, failedRequest) + ctx.store.clearPendingLoadMetrics(envCtx.scope, failedRequest) ctx.store.recordLoad(envCtx.scope, id, id, { name: 'vite:load-fallback', result: source, start: 20, end: 22, }, undefined, successfulRequest) - ctx.store.finishLoadRequest(envCtx.scope, successfulRequest) + ctx.store.clearPendingLoadMetrics(envCtx.scope, successfulRequest) const [module] = await envCtx.getModulesList() expect(module).toMatchObject({ totalTime: 22, sourceSize: source.length, distSize: source.length }) @@ -1139,8 +1139,8 @@ describe('vite inspect context', () => { start: 83, end: 85, }, source, undefined, successfulRequest) - ctx.store.finishLoadRequest(envCtx.scope, failedRequest) - ctx.store.finishLoadRequest(envCtx.scope, successfulRequest) + ctx.store.clearPendingLoadMetrics(envCtx.scope, failedRequest) + ctx.store.clearPendingLoadMetrics(envCtx.scope, successfulRequest) expect((await envCtx.getModuleTransformInfo(id)).transforms).toMatchObject([ { name: '__load__', result: source }, diff --git a/packages/vite/src/node/inspect/module.ts b/packages/vite/src/node/inspect/module.ts index b9cf126a0..a55e67392 100644 --- a/packages/vite/src/node/inspect/module.ts +++ b/packages/vite/src/node/inspect/module.ts @@ -31,12 +31,12 @@ export async function getModulesList( const transformList = await ctx.inspectContext.store.getTransformList(ctx.scope) const resolveIdList = await ctx.inspectContext.store.getResolveIdList(ctx.scope) - const declinedLoads = await ctx.inspectContext.store.getDeclinedLoadMetrics(ctx.scope) - const declinedLoadsById = new Map() - for (const load of declinedLoads) { - const plugins = declinedLoadsById.get(load.publicModuleId) ?? [] + const declinedLoadMetrics = await ctx.inspectContext.store.getDeclinedLoadMetrics(ctx.scope) + const declinedLoadMetricsById = new Map() + for (const load of declinedLoadMetrics) { + const plugins = declinedLoadMetricsById.get(load.publicModuleId) ?? [] plugins.push({ name: load.pluginName, transform: load.totalTime }) - declinedLoadsById.set(load.publicModuleId, plugins) + declinedLoadMetricsById.set(load.publicModuleId, plugins) } const transformsById = transformList.reduce>((map, transform) => { @@ -70,7 +70,7 @@ export async function getModulesList( name: resolveId.name, resolveId: resolveId.end - resolveId.start, })) - const loadPlugins = declinedLoadsById.get(ctx.getPublicModuleId(id)) ?? [] + const loadPlugins = declinedLoadMetricsById.get(ctx.getPublicModuleId(id)) ?? [] totalTime += loadPlugins.reduce((sum, plugin) => sum + (plugin.transform ?? 0), 0) const plugins = transformPlugins.concat(loadPlugins, resolveIdPlugins) const firstTransform = transforms[0] diff --git a/packages/vite/src/node/inspect/server.ts b/packages/vite/src/node/inspect/server.ts index 2f5e7debf..b7aaaa29e 100644 --- a/packages/vite/src/node/inspect/server.ts +++ b/packages/vite/src/node/inspect/server.ts @@ -65,7 +65,7 @@ export function setupEnvironmentInvalidation(server: ViteDevServer, vite: ViteIn return transformRequestStorage.run(request, () => transformRequest.apply(this, args)) .finally(() => { for (const context of state.contexts) - context.inspectContext.store.finishLoadRequest(context.scope, request) + context.inspectContext.store.clearPendingLoadMetrics(context.scope, request) request.active = false request.ids.clear() state.activeRequests.delete(request) diff --git a/packages/vite/src/node/inspect/store/index.ts b/packages/vite/src/node/inspect/store/index.ts index a3b85e54c..44d7780b0 100644 --- a/packages/vite/src/node/inspect/store/index.ts +++ b/packages/vite/src/node/inspect/store/index.ts @@ -12,7 +12,7 @@ import type { PendingWrite, QueuedWrite, StoredViteInspectTransformInfo, - ViteInspectModuleLoadMetric, + ViteInspectDeclinedLoadMetric, ViteInspectPayloadRange, ViteInspectPluginMetricItem, ViteInspectResolveIdItem, @@ -32,7 +32,7 @@ const DEFAULT_MAX_BATCH_ITEMS = 256 const DEFAULT_MAX_BATCH_BYTES = 8 * 1024 * 1024 interface StoredModuleTransforms { - loadRequest?: object + transformRequest?: object publicModuleId: string invokeCount: number items: StoredViteInspectTransformInfo[] @@ -41,12 +41,12 @@ interface StoredModuleTransforms { interface ScopeData { transforms: Map resolveIds: Map - declinedLoads: Map> - pendingLoads: Map>> + declinedLoadMetrics: Map> + pendingLoadMetrics: Map>> } interface PreparedWrite { - write: Exclude + write: Exclude resultIndex?: number sourceIndex?: number sourcemapIndex?: number @@ -125,7 +125,7 @@ class PayloadViteInspectStore implements ViteInspectStore { info: ViteInspectTransformInfo, preTransformCode: string, pluginCall?: ViteInspectPluginCallInfo, - loadRequest?: object, + transformRequest?: object, ): void { this.enqueue({ operation: 'recordTransform', @@ -135,7 +135,7 @@ class PayloadViteInspectStore implements ViteInspectStore { info, preTransformCode, pluginCall, - loadRequest, + transformRequest, }) } @@ -145,7 +145,7 @@ class PayloadViteInspectStore implements ViteInspectStore { publicModuleId: string, info: ViteInspectTransformInfo, pluginCall?: ViteInspectPluginCallInfo, - loadRequest?: object, + transformRequest?: object, ): void { this.enqueue({ operation: 'recordLoad', @@ -154,7 +154,7 @@ class PayloadViteInspectStore implements ViteInspectStore { publicModuleId, info, pluginCall, - loadRequest, + transformRequest, }) } @@ -177,17 +177,17 @@ class PayloadViteInspectStore implements ViteInspectStore { }) } - recordPluginCall(scope: string, info: ViteInspectPluginCallInfo, loadRequest?: object): void { + recordPluginCall(scope: string, info: ViteInspectPluginCallInfo, transformRequest?: object): void { this.enqueue({ operation: 'recordPluginCall', scope, info, - loadRequest, + transformRequest, }) } - finishLoadRequest(scope: string, loadRequest: object): void { - this.enqueue({ operation: 'finishLoadRequest', scope, loadRequest }) + clearPendingLoadMetrics(scope: string, transformRequest: object): void { + this.enqueue({ operation: 'clearPendingLoadMetrics', scope, transformRequest }) } invalidate(scope: string, moduleId: string, publicModuleId: string): void { @@ -227,9 +227,9 @@ class PayloadViteInspectStore implements ViteInspectStore { return result } - async getDeclinedLoadMetrics(scope: string): Promise { + async getDeclinedLoadMetrics(scope: string): Promise { await this.flush() - return Array.from(this.scopes.get(scope)?.declinedLoads ?? []).flatMap(([publicModuleId, metrics]) => + return Array.from(this.scopes.get(scope)?.declinedLoadMetrics ?? []).flatMap(([publicModuleId, metrics]) => Array.from(metrics.values(), metric => ({ ...metric, publicModuleId })), ) } @@ -421,7 +421,7 @@ class PayloadViteInspectStore implements ViteInspectStore { } private async writeBatch(batch: PendingWrite[]): Promise { - let dataWrites: Array> = [] + let dataWrites: Array> = [] const flushDataWrites = async () => { if (dataWrites.length === 0) return @@ -435,9 +435,9 @@ class PayloadViteInspectStore implements ViteInspectStore { await flushDataWrites() this.invalidateNow(write.scope, write.moduleId, write.publicModuleId) } - else if (write.operation === 'finishLoadRequest') { + else if (write.operation === 'clearPendingLoadMetrics') { await flushDataWrites() - this.scopes.get(write.scope)?.pendingLoads.delete(write.loadRequest) + this.scopes.get(write.scope)?.pendingLoadMetrics.delete(write.transformRequest) } else if (write.operation === 'clearScope') { await flushDataWrites() @@ -451,25 +451,25 @@ class PayloadViteInspectStore implements ViteInspectStore { } private async writeDataBatch( - writes: Array>, + writes: Array>, ): Promise { const values: Array = [] const prepared: PreparedWrite[] = [] const pluginCallWrites: InspectPluginCallWrite[] = [] - const sourceState = new Map() + const sourceState = new Map() - const hasSource = (scope: string, moduleId: string, loadRequest?: object): boolean => { + const hasSource = (scope: string, moduleId: string, transformRequest?: object): boolean => { const key = scopeKey(scope, moduleId) let state = sourceState.get(key) if (!state) { const stored = this.scopes.get(scope)?.transforms.get(moduleId) state = { hasSource: stored?.items.some(item => item.hasResult) ?? false, - loadRequest: stored?.loadRequest, + transformRequest: stored?.transformRequest, } sourceState.set(key, state) } - return state.hasSource && (!loadRequest || state.loadRequest === loadRequest) + return state.hasSource && (!transformRequest || state.transformRequest === transformRequest) } for (const write of writes) { @@ -486,9 +486,9 @@ class PayloadViteInspectStore implements ViteInspectStore { const item: PreparedWrite = { write } if (write.operation === 'recordTransform') { const key = scopeKey(write.scope, write.moduleId) - if (!hasSource(write.scope, write.moduleId, write.loadRequest)) { + if (!hasSource(write.scope, write.moduleId, write.transformRequest)) { item.sourceIndex = values.push(write.preTransformCode) - 1 - sourceState.set(key, { hasSource: true, loadRequest: write.loadRequest }) + sourceState.set(key, { hasSource: true, transformRequest: write.transformRequest }) } item.resultIndex = values.push(write.info.result) - 1 item.sourcemapIndex = pushSerializedPayload(values, write.info.sourcemaps) @@ -496,7 +496,7 @@ class PayloadViteInspectStore implements ViteInspectStore { else if (write.operation === 'recordLoad') { item.resultIndex = values.push(write.info.result) - 1 item.sourcemapIndex = pushSerializedPayload(values, write.info.sourcemaps) - sourceState.set(scopeKey(write.scope, write.moduleId), { hasSource: write.info.result != null, loadRequest: write.loadRequest }) + sourceState.set(scopeKey(write.scope, write.moduleId), { hasSource: write.info.result != null, transformRequest: write.transformRequest }) } prepared.push(item) } @@ -532,15 +532,15 @@ class PayloadViteInspectStore implements ViteInspectStore { else if (write.operation === 'recordPluginCall' && write.info.type === 'load') { // Declined loads have timing data but must not replace the module's code. const data = this.getScope(write.scope) - let pendingLoads = data.pendingLoads.get(write.loadRequest) - if (!pendingLoads) { - pendingLoads = new Map() - data.pendingLoads.set(write.loadRequest, pendingLoads) + let pendingLoadMetrics = data.pendingLoadMetrics.get(write.transformRequest) + if (!pendingLoadMetrics) { + pendingLoadMetrics = new Map() + data.pendingLoadMetrics.set(write.transformRequest, pendingLoadMetrics) } - let metrics = pendingLoads.get(write.info.module) + let metrics = pendingLoadMetrics.get(write.info.module) if (!metrics) { metrics = new Map() - pendingLoads.set(write.info.module, metrics) + pendingLoadMetrics.set(write.info.module, metrics) } addMetric(metrics, write.info.plugin_id, write.info.plugin_name, write.info.duration) } @@ -574,11 +574,11 @@ class PayloadViteInspectStore implements ViteInspectStore { let transforms = data.transforms.get(write.moduleId) // A new request can reach transform through Vite's direct file read. // Replace the previous snapshot even when it contains a load error result. - if (!transforms || (write.loadRequest && transforms.loadRequest !== write.loadRequest)) { + if (!transforms || (write.transformRequest && transforms.transformRequest !== write.transformRequest)) { if (transforms) this.payloads.reclaim(collectPayloadRanges(transforms.items)) transforms = { - loadRequest: write.loadRequest, + transformRequest: write.transformRequest, publicModuleId: write.publicModuleId, invokeCount: transforms?.invokeCount ?? 0, items: [], @@ -588,7 +588,7 @@ class PayloadViteInspectStore implements ViteInspectStore { if (!transforms.items.some(item => item.hasResult)) { // Vite can read files itself without a successful load hook. - this.commitLoadMetrics(data, write.publicModuleId, write.loadRequest) + this.commitDeclinedLoadMetrics(data, write.publicModuleId, write.transformRequest) transforms.items.push({ name: DUMMY_LOAD_PLUGIN_NAME, hasResult: true, @@ -609,29 +609,29 @@ class PayloadViteInspectStore implements ViteInspectStore { sourcemaps: ViteInspectPayloadRange | undefined, ): void { const data = this.getScope(write.scope) - this.commitLoadMetrics(data, write.publicModuleId, write.loadRequest) + this.commitDeclinedLoadMetrics(data, write.publicModuleId, write.transformRequest) const existing = data.transforms.get(write.moduleId) if (existing) this.payloads.reclaim(collectPayloadRanges(existing.items)) data.transforms.set(write.moduleId, { - loadRequest: write.loadRequest, + transformRequest: write.transformRequest, publicModuleId: write.publicModuleId, invokeCount: (existing?.invokeCount ?? 0) + 1, items: [toStoredTransformInfo(write.info, result, sourcemaps)], }) } - private commitLoadMetrics(data: ScopeData, publicModuleId: string, loadRequest?: object): void { + private commitDeclinedLoadMetrics(data: ScopeData, publicModuleId: string, transformRequest?: object): void { // Only this request can contribute declined loads to its code snapshot. - const pendingLoads = data.pendingLoads.get(loadRequest) - const declinedLoads = pendingLoads?.get(publicModuleId) - if (declinedLoads) - data.declinedLoads.set(publicModuleId, declinedLoads) + const pendingLoadMetrics = data.pendingLoadMetrics.get(transformRequest) + const declinedLoadMetrics = pendingLoadMetrics?.get(publicModuleId) + if (declinedLoadMetrics) + data.declinedLoadMetrics.set(publicModuleId, declinedLoadMetrics) else - data.declinedLoads.delete(publicModuleId) - pendingLoads?.delete(publicModuleId) - if (pendingLoads?.size === 0) - data.pendingLoads.delete(loadRequest) + data.declinedLoadMetrics.delete(publicModuleId) + pendingLoadMetrics?.delete(publicModuleId) + if (pendingLoadMetrics?.size === 0) + data.pendingLoadMetrics.delete(transformRequest) } private invalidateNow(scope: string, moduleId: string, publicModuleId: string): void { @@ -683,11 +683,11 @@ class PayloadViteInspectStore implements ViteInspectStore { } for (const id of invalidPublicIds) { - data.declinedLoads.delete(id) - for (const [request, pendingLoads] of data.pendingLoads) { - pendingLoads.delete(id) - if (pendingLoads.size === 0) - data.pendingLoads.delete(request) + data.declinedLoadMetrics.delete(id) + for (const [request, pendingLoadMetrics] of data.pendingLoadMetrics) { + pendingLoadMetrics.delete(id) + if (pendingLoadMetrics.size === 0) + data.pendingLoadMetrics.delete(request) } } @@ -754,8 +754,8 @@ class PayloadViteInspectStore implements ViteInspectStore { data = { transforms: new Map(), resolveIds: new Map(), - declinedLoads: new Map(), - pendingLoads: new Map(), + declinedLoadMetrics: new Map(), + pendingLoadMetrics: new Map(), } this.scopes.set(scope, data) } @@ -928,7 +928,7 @@ function positiveInteger(value: number | undefined, fallback: number): number { } function estimateWriteBytes(write: QueuedWrite): number { - const pluginCall = write.operation === 'invalidate' || write.operation === 'clearScope' || write.operation === 'finishLoadRequest' + const pluginCall = write.operation === 'invalidate' || write.operation === 'clearScope' || write.operation === 'clearPendingLoadMetrics' ? undefined : getQueuedPluginCall(write) const pluginCallBytes = pluginCall @@ -952,7 +952,7 @@ function estimateWriteBytes(write: QueuedWrite): number { } function getQueuedPluginCall( - write: Exclude, + write: Exclude, ): ViteInspectPluginCallInfo | undefined { return write.operation === 'recordPluginCall' ? write.info : write.pluginCall } diff --git a/packages/vite/src/node/inspect/store/types.ts b/packages/vite/src/node/inspect/store/types.ts index 4027cd52b..e66e452a9 100644 --- a/packages/vite/src/node/inspect/store/types.ts +++ b/packages/vite/src/node/inspect/store/types.ts @@ -70,7 +70,7 @@ export interface ViteInspectPluginMetricItem { totalTime: number } -export interface ViteInspectModuleLoadMetric extends ViteInspectPluginMetricItem { +export interface ViteInspectDeclinedLoadMetric extends ViteInspectPluginMetricItem { publicModuleId: string } @@ -82,7 +82,7 @@ export interface ViteInspectStore { info: ViteInspectTransformInfo, preTransformCode: string, pluginCall?: ViteInspectPluginCallInfo, - loadRequest?: object, + transformRequest?: object, ) => void recordLoad: ( scope: string, @@ -90,7 +90,7 @@ export interface ViteInspectStore { publicModuleId: string, info: ViteInspectTransformInfo, pluginCall?: ViteInspectPluginCallInfo, - loadRequest?: object, + transformRequest?: object, ) => void recordResolveId: ( scope: string, @@ -103,13 +103,13 @@ export interface ViteInspectStore { recordPluginCall: ( scope: string, info: ViteInspectPluginCallInfo, - loadRequest?: object, + transformRequest?: object, ) => void - finishLoadRequest: (scope: string, loadRequest: object) => void + clearPendingLoadMetrics: (scope: string, transformRequest: object) => void invalidate: (scope: string, moduleId: string, publicModuleId: string) => void clearScope: (scope: string) => void getTransformList: (scope: string) => Promise - getDeclinedLoadMetrics: (scope: string) => Promise + getDeclinedLoadMetrics: (scope: string) => Promise getResolveIdList: (scope: string) => Promise getPluginTransformMetrics: (scope: string) => Promise getPluginResolveIdMetrics: (scope: string) => Promise @@ -132,7 +132,7 @@ export type QueuedWrite info: ViteInspectTransformInfo preTransformCode: string pluginCall?: ViteInspectPluginCallInfo - loadRequest?: object + transformRequest?: object } | { operation: 'recordLoad' @@ -141,7 +141,7 @@ export type QueuedWrite publicModuleId: string info: ViteInspectTransformInfo pluginCall?: ViteInspectPluginCallInfo - loadRequest?: object + transformRequest?: object } | { operation: 'recordResolveId' @@ -156,12 +156,12 @@ export type QueuedWrite operation: 'recordPluginCall' scope: string info: ViteInspectPluginCallInfo - loadRequest?: object + transformRequest?: object } | { - operation: 'finishLoadRequest' + operation: 'clearPendingLoadMetrics' scope: string - loadRequest: object + transformRequest: object } | { operation: 'invalidate'