Skip to content

Commit a707e86

Browse files
committed
Pre-bundle late-discovered deps so the dev worker never program-reloads mid-suite
vite was discovering effect/Match, effect/Predicate, and js-yaml during test runs instead of at boot, forcing a re-optimize and full program reload on both the client and SSR (workerd) environments. Each reload strands the previous worker program's heap inside workerd, and a handful of them exhausts its heap limit and kills the dev server mid-shard. Adding these to optimizeDeps.include (client) and environments.ssr.optimizeDeps.include (SSR) in apps/cloud and apps/host-selfhost's vite configs makes vite bundle them at boot instead, so no mid-run discovery happens. js-yaml is a transitive dependency via @executor-js/plugin-openapi that bun's isolated install doesn't hoist into either app's node_modules, so a bare "js-yaml" specifier silently fails to resolve in optimizeDeps.include. Used vite's "<pkg> > <dep>" nested resolution syntax to resolve it from the owning package instead.
1 parent 8cc1e3f commit a707e86

2 files changed

Lines changed: 65 additions & 0 deletions

File tree

apps/cloud/vite.config.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,32 @@ export default defineConfig(({ command, mode }) => {
6565
delete (publicEnv as Record<string, string | undefined>).VITE_PUBLIC_OTLP_TRACES_URL;
6666
}
6767

68+
// Deps vite only discovers once a lazy-loaded React chunk actually renders
69+
// (e.g. opening the MCP/OpenAPI "add source" flow). Discovering them mid-run
70+
// forces a re-optimize + full program reload; in workerd (apps/cloud's SSR
71+
// worker) each reload stacks a new isolate's heap on top of the last one
72+
// without freeing it, so a handful of reloads exhausts the worker's heap
73+
// limit and crashes the dev server. Pre-bundling them at boot means vite
74+
// never discovers them mid-run, so it never reloads. Keep this list scoped
75+
// to deps actually imported by UI code (grep `from "effect/` under
76+
// packages/react/src and packages/plugins/*/src/react, plus js-yaml pulled
77+
// in via packages/plugins/openapi/src/sdk) rather than including the world.
78+
// js-yaml is a transitive dep (via @executor-js/plugin-openapi), not hoisted
79+
// into apps/cloud/node_modules under bun's isolated install, so a plain
80+
// "js-yaml" specifier fails to resolve here and silently falls out of the
81+
// pre-bundle. The "<pkg> > <dep>" syntax resolves it starting from that
82+
// package's own node_modules instead.
83+
const lateDiscoveredDeps = [
84+
"effect/Match",
85+
"effect/Predicate",
86+
"effect/Exit",
87+
"effect/Option",
88+
"effect/Cause",
89+
"effect/Data",
90+
"effect/Schema",
91+
"@executor-js/plugin-openapi > js-yaml",
92+
];
93+
6894
return {
6995
define: Object.fromEntries(
7096
Object.entries(publicEnv)
@@ -81,6 +107,22 @@ export default defineConfig(({ command, mode }) => {
81107
},
82108
},
83109
resolve: { tsconfigPaths: true },
110+
// Client-side pre-bundle. See lateDiscoveredDeps comment above.
111+
optimizeDeps: {
112+
include: lateDiscoveredDeps,
113+
},
114+
// SSR/worker-side pre-bundle for the same deps, keyed under the "ssr"
115+
// environment name that `cloudflare({ viteEnvironment: { name: "ssr" } })`
116+
// below uses. The cloudflare plugin sets its own environments.ssr.optimizeDeps
117+
// (entries/exclude for worker externals); vite merges include arrays rather
118+
// than replacing them, so this only adds to that, it doesn't fight it.
119+
environments: {
120+
ssr: {
121+
optimizeDeps: {
122+
include: lateDiscoveredDeps,
123+
},
124+
},
125+
},
84126
plugins: [
85127
devCrashGuard(),
86128
tailwindcss(),

apps/host-selfhost/vite.config.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,29 @@ export default defineConfig({
190190
alias: { "@executor-app": APP_ROOT },
191191
dedupe: ["react", "react-dom"],
192192
},
193+
// This SPA shares packages/app's shell and packages/react's lazy-loaded
194+
// "add source" UI with apps/cloud, so the same deps only surface once a
195+
// lazy chunk actually renders (e.g. opening the MCP/OpenAPI add-source
196+
// flow). Pre-bundle them at boot so vite never discovers them mid-run and
197+
// never has to re-optimize + reload. No SSR/worker environment here (this
198+
// app has no cloudflare plugin, it's a plain SPA build), so only the
199+
// client optimizeDeps applies. Keep in sync with apps/cloud/vite.config.ts.
200+
// js-yaml is a transitive dep (via @executor-js/plugin-openapi) that isn't
201+
// hoisted into this app's node_modules under bun's isolated install, so a
202+
// plain "js-yaml" specifier fails to resolve; "<pkg> > <dep>" resolves it
203+
// from that package's own node_modules instead.
204+
optimizeDeps: {
205+
include: [
206+
"effect/Match",
207+
"effect/Predicate",
208+
"effect/Exit",
209+
"effect/Option",
210+
"effect/Cause",
211+
"effect/Data",
212+
"effect/Schema",
213+
"@executor-js/plugin-openapi > js-yaml",
214+
],
215+
},
193216
define: {
194217
"import.meta.env.VITE_APP_VERSION": JSON.stringify(EXECUTOR_VERSION ?? "0.0.0"),
195218
// Self-host upgrades by pulling/rebuilding the image (or git + rebuild), not

0 commit comments

Comments
 (0)