diff --git a/src/servers/plugins/generate.ts b/src/servers/plugins/generate.ts index 61d43012..b8a8849f 100644 --- a/src/servers/plugins/generate.ts +++ b/src/servers/plugins/generate.ts @@ -212,6 +212,27 @@ export async function rebuildFrontend(): Promise { plugins: [tailwind], minify: process.env.NODE_ENV === 'production', sourcemap: 'none', + /* + WITHOUT THIS A PLUGIN CAN TAKE THE WHOLE APP DOWN WITH ONE LINE. + + `scripts/build/web.ts` — the platform's own bundle — defines `process.env.NODE_ENV`. This build + defined nothing, so any `process.*` in a plugin's frontend was emitted verbatim into a browser + chunk and threw `ReferenceError: process is not defined` at module evaluation. One throwing module + fails the whole graph, so the symptom is not a broken panel, it is a blank platform. + + Reached by vendored code rather than by anyone writing Node in a component: m3e-canvas carries four + files from a Next.js original that read `process.env.NEXT_PUBLIC_BASE_PATH`. Vendored trees stay + close to upstream here (see the hls.js note in CLAUDE.md), so the build is the right place to + absorb it — and it protects every plugin rather than the one that happened to hit it. + + Both keys, and the order does not matter: the longest match wins, so `NODE_ENV` keeps its real + value and every other `process.env.X` becomes `({}).X`, which is `undefined` — exactly what the + `?? ''` in that vendored code expects. Verified against `bun build` rather than assumed. + */ + define: { + 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV === 'production' ? 'production' : 'development'), + 'process.env': '({})', + }, }); if (!result.success) { return {