[EmDash] Note `ssr.optimizeDeps.include` Fixes Vite 7's SSR Dep Optimizer Race Condition and Stale Chunk Crashes on Cloudflare Workers
When I migrated my personal site to Astro 6 + EmDash CMS on Cloudflare Workers, I hit a dev-server crash that took a while to diagnose. Every time I ran `pnpm dev:ui`, the first request would return many errors about missing chunk files. This post explains what was happening, what I tried that didn't work, and the fix that actually solved it.
The Stack
- Astro 6.3.3
- Vite 7.3.3 (pinned via `pnpm.overrides` — Astro 6's bundled rolldown-vite breaks `@cloudflare/vite-plugin`)
- EmDash CMS 0.10.0 (`emdash` + `@emdash-cms/cloudflare`)
- `@astrojs/cloudflare` adapter with `remoteBindings: true`
- `@cloudflare/vite-plugin` 1.37.0
- Miniflare 4.20260511.0 (embedded in the Cloudflare plugin)
The Error
[vite] ✨ new dependencies optimized: emdash/middleware, emdash/middleware/redirect,
emdash/middleware/setup, emdash/middleware/auth, emdash/middleware/request-context
[vite] ✨ optimized dependencies changed. reloading
[vite] ✨ new dependencies optimized: @emdash-cms/cloudflare/db/d1, emdash/ui
[vite] ✨ optimized dependencies changed. reloading
[vite] ✨ new dependencies optimized: emdash/media/local-runtime
[vite] ✨ optimized dependencies changed. reloading
[vite] ✨ new dependencies optimized: @emdash-cms/cloudflare/storage/r2
[vite] ✨ optimized dependencies changed. reloading
[vite] An error happened during full reload
The file does not exist at
".../node_modules/.vite/deps_ssr/chunk-GGAS75JV.js?v=d3e10cf3"
which is in the optimize deps directory. The dependency might be
incompatible with the dep optimizer. Try adding it to `optimizeDeps.exclude`. And from inside the EmDash admin, two follow-on warnings:
[emdash] Failed to hydrate bylines: The file does not exist at
".../deps_ssr/bylines-esI7ioa9-Z3OQX3NW.js?v=98f1f127"
[emdash] Failed to hydrate terms: The file does not exist at
".../deps_ssr/taxonomies-CTtewrSQ-Z5QGP4FL.js?v=98f1f127" Understanding the Scene: Two Separate Optimizers
In Vite 5 and earlier, `optimizeDeps` settings were largely shared between browser and SSR environments. Vite 7 separates them completely.
- `optimizeDeps` — controls pre-bundling for the browser/client environment
- `ssr.optimizeDeps` — controls pre-bundling for the SSR environment
They're independent. Setting `optimizeDeps.exclude: ["emdash"]` only excluded EmDash from the client optimizer. The SSR optimizer was still free to lazily discover and re-optimize sub-paths at request time.
The Fix: `ssr.optimizeDeps.include`
The correct lever is `ssr.optimizeDeps.include`. This tells Vite to force-include specific packages in the initial SSR optimization scan — before any request is served.
vite: {
plugins: [tailwindcss()],
optimizeDeps: {
exclude: ["emdash"],
},
ssr: {
optimizeDeps: {
include: [
"emdash/middleware",
"emdash/middleware/auth",
"emdash/middleware/redirect",
"emdash/middleware/request-context",
"emdash/middleware/setup",
"emdash/runtime",
"emdash/ui",
"emdash/media/local-runtime",
"@emdash-cms/cloudflare/db/d1",
"@emdash-cms/cloudflare/storage/r2",
"astro/zod",
],
},
},
}, Why This Works
By listing the packages in `ssr.optimizeDeps.include`, Vite pulls them into the startup optimization pass before the dev server accepts requests. That eliminates lazy discovery rounds, stale chunk invalidations, and mid-request hash churn.
The SSR optimizer still performs its CJS→ESM transformation work — it just does it upfront in a single pass instead of reactively during requests.