Astro v6.1.6
Vite v7.3.2
Node v25.9.0
System macOS (x64)
Package Manager npm
Output static
Adapter @astrojs/cloudflare (v13.1.9)
Integrations none
During astro build, the syncInternal function in core/sync/index.js creates a temporary Vite dev server (createTempViteServer) to resolve content collection configs and generate type declarations. Because this is a real dev server (created via Vite's createServer), every plugin's configureServer hook runs — including adapter plugins that start heavy runtimes.
With @astrojs/cloudflare, the @cloudflare/vite-plugin hooks into configureServer to start miniflare (the workerd runtime). This adds ~1–3.5 s of overhead on every build, even though the temp server only needs to resolve virtual modules for type generation. It never handles HTTP requests.
The overhead is especially noticeable in CI and in server-mode builds where the actual Vite build phases (prerender + SSR + client) can be as low as ~1.5 s for a small project — making the sync overhead ~40% of the total build time.
| Phase | Time |
|---|---|
| Types Generated (sync) | 1.24 s |
| Prerender build | 0.88 s |
| SSR build | 0.66 s |
| Client build | 0.007 s |
| Total build | 3.30 s |
| Phase | Before fix | After fix |
|---|---|---|
| Types Generated | 3.6 s | 125 ms |
| Total build | ~13 s | ~9.2 s |
Two issues combine:
-
Astro's sync creates a full dev server (
createServer) when a lighter-weight approach would suffice for resolving virtual modules and generating types. The temp server config already passes{ middlewareMode: true, hmr: false, watch: null, ws: false }— butconfigureServerhooks still fire. -
optimizeDeps: { noDiscovery: true }only applies at the top level (client environment). In Vite 7's Environment API, the Cloudflare adapter'sconfigEnvironmenthook checks_options.optimizeDeps?.noDiscoveryper-environment. Since server environments (ssr, astro, prerender) don't inherit the top-level flag, the adapter injects its largeoptimizeDeps.includelist (~30 entries), forcing the optimizer to pre-bundle them even in the temp server.
Type generation during astro build should not start miniflare or perform dependency pre-bundling in adapter-managed environments. For a minimal project, this phase should complete in < 250 ms, not > 1 s.
The createTempViteServer function in core/sync/index.js should:
- Set
optimizeDeps.noDiscoveryon every environment, not just the top level, so adapterconfigEnvironmenthooks see the flag and skip their include lists:
const noOptimize = { optimizeDeps: { noDiscovery: true, include: [] } };
// passed to createVite:
environments: {
client: noOptimize,
ssr: noOptimize,
astro: noOptimize,
prerender: noOptimize,
},- Strip
configureServerhooks from adapter plugins that start runtimes, since the temp server never serves requests:
plugins: [{
name: "sync:strip-adapter-hooks",
enforce: "pre",
configResolved(config) {
for (const plugin of config.plugins) {
if (plugin.configureServer && /cloudflare/.test(plugin.name)) {
delete plugin.configureServer;
}
}
}
}]A more general solution might be to use Vite's ModuleRunner directly instead of creating a full dev server, but the plugin-stripping approach is a targeted fix that preserves the existing architecture.
https://github.com/adamchal/astro-sync-perf
- I am willing to submit a pull request for this issue.