From fd760775ef97308ca110d4b774aaba8ed70c11f9 Mon Sep 17 00:00:00 2001 From: Alexander Lichter Date: Mon, 18 May 2026 15:55:21 +0200 Subject: [PATCH 1/2] fix(void): strip `resolve.external` from worker environment in Vite plugin --- packages/void/src/index.ts | 17 ++++++++++ .../test/unit/plugin-vite-environment.test.ts | 32 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/packages/void/src/index.ts b/packages/void/src/index.ts index df6d91f72..82374d2a0 100644 --- a/packages/void/src/index.ts +++ b/packages/void/src/index.ts @@ -396,6 +396,22 @@ function createDefaultWorkerEnvironmentPlugin(): Plugin { }; } +function createWorkerEnvironmentSanitizerPlugin(): Plugin { + return { + name: 'void:worker-environment-sanitizer', + enforce: 'pre', + configResolved(config) { + const resolve = config.environments[DEFAULT_WORKER_ENVIRONMENT_NAME]?.resolve; + if (resolve && 'external' in resolve) { + // Test runners may seed Node externals into every Vite environment. + // Cloudflare Worker environments cannot externalize dependencies, but + // Cloudflare's validator expects the normalized array shape to remain. + resolve.external = []; + } + }, + }; +} + function createSandboxSdkResolvePlugin(): Plugin { let resolved: string | undefined; @@ -1488,6 +1504,7 @@ export function voidPlugin(options?: { return [ createCloudflareBuiltinsExternalPlugin(), createDefaultWorkerEnvironmentPlugin(), + createWorkerEnvironmentSanitizerPlugin(), createWranglerCompatPersistPlugin(root, config), restartPlugin(), bindingWatchPlugin, diff --git a/packages/void/test/unit/plugin-vite-environment.test.ts b/packages/void/test/unit/plugin-vite-environment.test.ts index 3c20eb107..4e388f449 100644 --- a/packages/void/test/unit/plugin-vite-environment.test.ts +++ b/packages/void/test/unit/plugin-vite-environment.test.ts @@ -79,4 +79,36 @@ describe('voidPlugin Vite environments', () => { }, }); }); + + it('clears resolve.external from the worker environment configured by test runners', async () => { + const root = createProjectRoot(); + vi.spyOn(process, 'cwd').mockReturnValue(root); + + const config = await resolveConfig( + { + root, + plugins: [voidPlugin()], + environments: { + void_worker: { + resolve: { + external: ['node:fs'], + conditions: ['workerd'], + }, + build: { + emptyOutDir: false, + }, + }, + }, + }, + 'serve', + 'test', + ); + + expect(config.environments.void_worker.resolve.external).toEqual([]); + expect(config.environments.void_worker.resolve.conditions).toContain('workerd'); + expect(config.environments.void_worker.build).toMatchObject({ + emptyOutDir: false, + outDir: 'dist/ssr', + }); + }); }); From dad3b926df5dc91b3b520fe6dcbbb8df096f3c3d Mon Sep 17 00:00:00 2001 From: Alexander Lichter Date: Mon, 18 May 2026 18:23:32 +0200 Subject: [PATCH 2/2] fix(void): sanitize framework worker environments --- packages/void/src/index.ts | 23 ++++++++----- .../test/unit/plugin-vite-environment.test.ts | 34 +++++++++++++++++++ 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/packages/void/src/index.ts b/packages/void/src/index.ts index 6f587bdbd..b5335a783 100644 --- a/packages/void/src/index.ts +++ b/packages/void/src/index.ts @@ -396,17 +396,20 @@ function createDefaultWorkerEnvironmentPlugin(): Plugin { }; } -function createWorkerEnvironmentSanitizerPlugin(): Plugin { +function createWorkerEnvironmentSanitizerPlugin(environmentNames: ReadonlyArray): Plugin { + const names = new Set(environmentNames); return { name: 'void:worker-environment-sanitizer', enforce: 'pre', configResolved(config) { - const resolve = config.environments[DEFAULT_WORKER_ENVIRONMENT_NAME]?.resolve; - if (resolve && 'external' in resolve) { - // Test runners may seed Node externals into every Vite environment. - // Cloudflare Worker environments cannot externalize dependencies, but - // Cloudflare's validator expects the normalized array shape to remain. - resolve.external = []; + for (const name of names) { + const resolve = config.environments[name]?.resolve; + if (resolve && 'external' in resolve) { + // Test runners may seed Node externals into every Vite environment. + // Cloudflare Worker environments cannot externalize dependencies, but + // Cloudflare's validator expects the normalized array shape to remain. + resolve.external = []; + } } }, }; @@ -1386,6 +1389,10 @@ export function voidPlugin(options?: { return [ createCloudflareBuiltinsExternalPlugin(), + createWorkerEnvironmentSanitizerPlugin([ + viteEnvironment.name, + ...(viteEnvironment.childEnvironments ?? []), + ]), createWranglerCompatPersistPlugin(root, config), restartPlugin(), bindingWatchPlugin, @@ -1516,7 +1523,7 @@ export function voidPlugin(options?: { return [ createCloudflareBuiltinsExternalPlugin(), createDefaultWorkerEnvironmentPlugin(), - createWorkerEnvironmentSanitizerPlugin(), + createWorkerEnvironmentSanitizerPlugin([DEFAULT_WORKER_ENVIRONMENT_NAME]), createWranglerCompatPersistPlugin(root, config), restartPlugin(), bindingWatchPlugin, diff --git a/packages/void/test/unit/plugin-vite-environment.test.ts b/packages/void/test/unit/plugin-vite-environment.test.ts index 4e388f449..ae2150333 100644 --- a/packages/void/test/unit/plugin-vite-environment.test.ts +++ b/packages/void/test/unit/plugin-vite-environment.test.ts @@ -111,4 +111,38 @@ describe('voidPlugin Vite environments', () => { outDir: 'dist/ssr', }); }); + + it('clears resolve.external from class A framework worker environments', async () => { + const root = createProjectRoot(); + vi.spyOn(process, 'cwd').mockReturnValue(root); + writeFileSync( + join(root, 'package.json'), + JSON.stringify({ + type: 'module', + dependencies: { + '@tanstack/react-start': '^1.0.0', + }, + }), + ); + + const config = await resolveConfig( + { + root, + plugins: [voidPlugin()], + environments: { + ssr: { + resolve: { + external: ['node:fs'], + conditions: ['workerd'], + }, + }, + }, + }, + 'serve', + 'test', + ); + + expect(config.environments.ssr.resolve.external).toEqual([]); + expect(config.environments.ssr.resolve.conditions).toContain('workerd'); + }); });