a plugin's frontend gets the same defines as the platform's own

One line in a vendored plugin file took the whole app down. scripts/build/web.ts
defines process.env.NODE_ENV for the platform bundle; the plugin frontend build
in generate.ts defined nothing, so any process.* in a plugin's web code 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 a blank platform rather than a broken panel.

Hit on macbookpro after installing m3e-canvas, which carries four files from a
Next.js original reading process.env.NEXT_PUBLIC_BASE_PATH. This machine was
unaffected only because the plugin is on disk but not installed, so it never
entered Plugins.gen.tsx.

Defines process.env.NODE_ENV for parity and process.env to ({}) for the rest,
so every other process.env.X becomes undefined — which is what the `?? ''` in
that vendored code already expects. Longest match wins; verified against bun
build rather than assumed. Fixed in the build rather than in the vendored tree,
because vendored code stays close to upstream here and this protects every
plugin instead of the one that hit it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Officer-Session: f7a62308-0977-4cf4-aa29-c020853fd420
This commit is contained in:
2026-09-22 13:16:52 +01:00
co-authored by Claude Opus 5
parent f4147cef30
commit 06bed42ace
+21
View File
@@ -212,6 +212,27 @@ export async function rebuildFrontend(): Promise<BuildResult> {
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 {