diff --git a/clients/web/server/vite-base-config.ts b/clients/web/server/vite-base-config.ts index 3d9c1a90..5d4345a3 100644 --- a/clients/web/server/vite-base-config.ts +++ b/clients/web/server/vite-base-config.ts @@ -55,6 +55,13 @@ export function getViteBaseConfig() { // components import it at runtime (e.g. `protocolUtils`'s // `isInputRequiredResult` / `SUBSCRIPTION_ID_META_KEY`), so listing it // here keeps the dep graph stable across story files. + // + // That was one instance of a class, not the class: any package a story + // or component starts importing after the cache was written is + // discovered the same way, and pinning each one here would chase the + // symptom. The `storybook` project in `vite.config.ts` now sets + // `optimizeDeps.force` so every run re-scans the story entries up front + // (#2340); this entry stays as the explicit include it always was. include: ["@modelcontextprotocol/client"], }, }; diff --git a/clients/web/vite.config.ts b/clients/web/vite.config.ts index d6fea376..85ec909f 100644 --- a/clients/web/vite.config.ts +++ b/clients/web/vite.config.ts @@ -391,6 +391,24 @@ export default defineConfig(({ command }) => { configDir: path.join(dirname, ".storybook"), }), ], + optimizeDeps: { + // Re-bundle the browser dep pre-bundle on every run instead of + // trusting the cached one (#2340). Vite keys that cache on the + // lockfile and on this config, never on what the story graph + // imports, so a cached bundle stays "valid" after a story or + // component gains an import of a package that is already + // installed. The first request for it then re-runs the optimizer + // mid-run, which bumps the `?v=` browser hash and rewrites the + // shared chunks; the `@storybook/react` renderer already loaded in + // a live test iframe still holds the old hash for its lazy + // `import("@storybook/react-dom-shim")`, so every story that + // iframe renders from then on fails with "Failed to fetch + // dynamically imported module", and the next run is green because + // the cache has caught up. `force` discards the cache up front, so + // the scanner crawls every story entry before the browser opens — + // the same cold path CI takes on every PR. Cost: ~0.8s per run. + force: true, + }, test: { name: "storybook", // Vitest's default is 5000ms, which is the whole budget a play