Skip to content

Commit de63174

Browse files
authored
perf(browser): pre-bundle the vitest runtime in optimizeDeps (#10713)
1 parent 66d95af commit de63174

5 files changed

Lines changed: 39 additions & 13 deletions

File tree

packages/browser/src/node/index.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -431,23 +431,17 @@ function resolveBrowserOptimizeDeps(
431431
...(testConfig.snapshotSerializers || []),
432432
]
433433

434+
// Keep these external (never pre-bundle by optimizer):
435+
// - vitest/browser, @vitest/browser/context, @vitest/browser/utils are
436+
// VIRTUAL modules generated per-server (see pluginContext.ts) — optimizer
437+
// cannot resolve/run their `load`, it would freeze stale/empty content.
438+
// - vite/module-runner is small enough to not need pre-bundling.
439+
// - msw is a large, side-effectful service-worker library.
434440
const exclude = [
435-
'vitest',
436441
'vitest/browser',
437-
'vitest/internal/browser',
438442
'vite/module-runner',
439443
'@vitest/browser/utils',
440444
'@vitest/browser/context',
441-
'@vitest/browser/client',
442-
'@vitest/utils',
443-
'@vitest/utils/source-map',
444-
'@vitest/spy',
445-
'@vitest/utils/error',
446-
'std-env',
447-
'tinybench',
448-
'tinyspy',
449-
'tinyrainbow',
450-
'pathe',
451445
'msw',
452446
'msw/browser',
453447
]
@@ -477,10 +471,21 @@ function resolveBrowserOptimizeDeps(
477471
}
478472
}
479473

474+
// Pre-bundle the vitest runtime so the browser fetches a few optimized
475+
// chunks instead of ~20 separately-served dist chunks (faster startup).
476+
// `vitest`, `vitest/internal/browser` and `@vitest/browser/client` are
477+
// optimized together in a single pass, so esbuild dedupes their shared
478+
// stateful chunks (the test collector, the runner, the RPC client) to a
479+
// single instance — preserving module identity between the test files'
480+
// `import 'vitest'` and the tester. Their transitive deps (@vitest/utils,
481+
// @vitest/spy, pathe, tinyrainbow, …) are inlined into these bundles.
480482
const include = [
481483
'vitest > expect-type',
482484
'vitest > magic-string',
483485
'vitest > chai',
486+
'vitest',
487+
'vitest/internal/browser',
488+
'@vitest/browser/client',
484489
]
485490

486491
const provider = testConfig.browser?.provider

packages/utils/src/source-map.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const stackIgnorePatterns: (string | RegExp)[] = [
3939
/__vitest_browser__/,
4040
'/@id/__x00__vitest/browser',
4141
/\/deps\/vitest_/,
42+
'/deps/vitest.js',
4243
]
4344

4445
export { stackIgnorePatterns as defaultStackIgnorePatterns }

packages/vitest/src/node/plugins/vitestResolver.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,18 @@ export function VitestCoreResolver(): Plugin {
4848
},
4949
async resolveId(id) {
5050
if (id === 'vitest') {
51+
// in environments that pre-bundle vitest (the browser `client`
52+
// environment), the optimizer's copy must win: the tester and the
53+
// test files have to share a single module instance, and returning
54+
// the dist file directly would bypass the optimized dep resolution
55+
if (this.environment?.config.optimizeDeps.include?.includes('vitest')) {
56+
const resolved = await this.resolve(id, join(root, 'index.html'), {
57+
skipSelf: true,
58+
})
59+
if (resolved) {
60+
return resolved
61+
}
62+
}
5163
return resolve(distDir, 'index.js')
5264
}
5365
if (id.startsWith('@vitest/') || id.startsWith('vitest/')) {

test/browser/specs/runner.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ describe('console logging tests', async () => {
181181
stdout,
182182
} = await runBrowserTests({
183183
root: './fixtures/print-logs',
184+
// assert on Vitest's own console forwarding rather than Vite's client
185+
// relay, which does not run when the tester loads the stubbed @vite/client
186+
reporters: ['default'],
184187
}))
185188
})
186189

test/e2e/test/reporters/merge-reports.test.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,11 +390,14 @@ test.for([
390390
"<root>/sub/subject.ts"
391391
],
392392
"<root>/basic.test.ts": [
393+
"<optimized-deps>/vitest.js",
393394
"<root>/sub/format.ts",
394395
"<root>/util.ts"
395396
]
396397
},
397-
"externalized": [],
398+
"externalized": [
399+
"<optimized-deps>/vitest.js?v=<hash>"
400+
],
398401
"inlined": [
399402
"<root>/basic.test.ts",
400403
"<root>/sub/format.ts",
@@ -409,11 +412,13 @@ test.for([
409412
"<root>/sub/subject.ts"
410413
],
411414
"<root>/second.test.ts": [
415+
"<optimized-deps>/vitest.js",
412416
"<root>/util.ts",
413417
"<optimized-deps>/obug.js"
414418
]
415419
},
416420
"externalized": [
421+
"<optimized-deps>/vitest.js?v=<hash>",
417422
"<optimized-deps>/obug.js?v=<hash>"
418423
],
419424
"inlined": [

0 commit comments

Comments
 (0)
Sponsor
SponsoredKunjungi sekarang
Promo