@@ -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
0 commit comments