···1313The phases map to configuration options:
14141515- `environment` - creating the test environment (for example `jsdom`, `happy-dom`) for test files.
1616-- `transform` - transforming files with Vite. See [Caching Between Reruns](#caching-between-reruns).
1717-- `import` - importing test files and their modules. When files import mostly the same modules (typical for barrel-file imports), isolation re-evaluates that shared graph for every file. See [Test Isolation](#test-isolation).
1616+- `transform` - waiting for Vite to resolve and transform imported modules. See [Caching Between Reruns](#caching-between-reruns).
1717+- `import` - evaluating test files and their modules, excluding the transform wait tracked above. When files import mostly the same modules (typical for barrel-file imports), isolation re-evaluates that shared graph for every file. See [Test Isolation](#test-isolation).
1818- `setup` - running [`setupFiles`](/config/setupfiles).
1919+- `worker` - preparing the test runner in each worker. Isolation pays this cost for every test file. See [Test Isolation](#test-isolation).
1920- `tests` - running the tests themselves. A run dominated by this phase has little to gain from configuration changes.
20212122## Test Isolation
···4343 getSafeWorkerState() || options.state
4444 const rpc = () => state().rpc
45454646+ // Wall time the worker spends blocked on server round-trips, measured as the
4747+ // union of in-flight intervals: sibling imports await fetches concurrently,
4848+ // so summing individual call durations would overcount the blocked time.
4949+ let fetchesInflight = 0
5050+ let fetchesBusyStart = 0
5151+ async function trackFetchTime<T>(fetchPromise: Promise<T>): Promise<T> {
5252+ if (fetchesInflight++ === 0) {
5353+ fetchesBusyStart = performance.now()
5454+ }
5555+ try {
5656+ return await fetchPromise
5757+ }
5858+ finally {
5959+ if (--fetchesInflight === 0) {
6060+ state().durations.fetch += performance.now() - fetchesBusyStart
6161+ }
6262+ }
6363+ }
6464+4665 const environment = () => {
4766 const environment = state().environment
4867 return environment.viteEnvironment || environment.name
···173192 // its import graph is connected on the server, so the snapshot
174193 // actually covers the file's transitive dependencies
175194 if (importer != null) {
176176- const warm = await fetchWarmModules()
195195+ const warm = await trackFetchTime(fetchWarmModules())
177196 // the null prototype is not preserved by the IPC serialization, so
178197 // ids like "constructor" must not fall through to Object.prototype
179198 const warmResult = warm && (
···200219 }
201220202221 const otelCarrier = traces?.getContextCarrier()
203203- const result = await rpc().fetch(
222222+ const result = await trackFetchTime(rpc().fetch(
204223 id,
205224 importer,
206225 environment(),
207226 options,
208227 otelCarrier,
209209- )
228228+ ))
210229 if ('cached' in result) {
211230 const code = readFileSync(result.tmp, 'utf-8')
212231 return { code, ...result }
+4-1
packages/vitest/src/runtime/runVmTests.ts
···8484 testRunner.cancel?.(reason)
8585 })
86868787+ // unlike other pools, the vm pool creates the environment inside the
8888+ // prepare window; subtract it so `prepare` excludes the environment
8989+ // load time in every pool
8790 workerState.durations.prepare
8888- = performance.now() - workerState.durations.prepare
9191+ = performance.now() - workerState.durations.prepare - workerState.durations.environment
89929093 const { vi } = VitestIndex
9194
···315315 */
316316 collectDuration?: number
317317 /**
318318+ * The portion of `collectDuration` the worker spent waiting for the server
319319+ * to resolve and transform modules.
320320+ */
321321+ collectFetchDuration?: number
322322+ /**
318323 * The time it took to import the setup file.
319324 */
320325 setupDuration?: number
326326+ /**
327327+ * The portion of `setupDuration` the worker spent waiting for the server
328328+ * to resolve and transform modules.
329329+ */
330330+ setupFetchDuration?: number
321331 /**
322332 * Whether the file is initiated without running any tests.
323333 * This is done to populate state on the server side by Vitest.
···17171727 * Gets the time spent importing each individual non-externalized file that Vitest collected.
17181728 */
17191729 getImportDurations?: () => Record<string, ImportDuration>
17301730+ /**
17311731+ * Gets the cumulative time the worker has spent waiting for the server to
17321732+ * resolve and transform modules. Used to attribute the transform wait to the
17331733+ * setup and collect phases.
17341734+ */
17351735+ getModuleFetchDuration?: () => number
17201736 /**
17211737 * Publicly available configuration.
17221738 */
···8787 durations: {
8888 environment: number
8989 prepare: number
9090+ /**
9191+ * Wall time the worker spent blocked on module fetch requests to the
9292+ * server, measured as the union of in-flight intervals.
9393+ */
9494+ fetch: number
9095 }
9196 onFilterStackTrace?: (trace: string) => string
9297}