History

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.

Rhys Sullivan committed 4 months ago

Commit a707e861 parent 8cc1e3f2 files · +65 −0Browse files

Unified · Split

2 files
  1. apps/cloud/vite.config.ts +42 −0
  2. apps/host-selfhost/vite.config.ts +23 −0
apps/cloud/vite.config.ts+42−0
@@ -65,6 +65,32 @@ export default defineConfig(({ command, mode }) => { · 64 unmodified lines
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 }) => { · 10 unmodified lines
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+23−0
@@ -190,6 +190,29 @@ export default defineConfig({ · 189 unmodified lines
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