diff --git a/packages/rolldown/src/node/rolldown/__tests__/build-runner.test.ts b/packages/rolldown/src/node/rolldown/__tests__/build-runner.test.ts index 5b7de119..2ce52a01 100644 --- a/packages/rolldown/src/node/rolldown/__tests__/build-runner.test.ts +++ b/packages/rolldown/src/node/rolldown/__tests__/build-runner.test.ts @@ -2,15 +2,30 @@ import type { ViteDevToolsNodeContext } from '@vitejs/devtools-kit' import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' -import { afterEach, describe, expect, it } from 'vitest' -import { getBuildCommand } from '../build-runner' +import { afterEach, describe, expect, it, vi } from 'vitest' +import { getBuildCommand, ROLLDOWN_DEVTOOLS_ENV, startBuild } from '../build-runner' const fixtures: string[] = [] afterEach(async () => { + vi.unstubAllEnvs() await Promise.all(fixtures.splice(0).map(dir => rm(dir, { recursive: true, force: true }))) }) +function fakeContext() { + const startChildProcess = vi.fn(async (_exec: unknown, meta: { id: string }) => ({ + ...meta, + status: 'running', + terminate: vi.fn(async () => {}), + getResult: vi.fn(), + })) + const context = { + cwd: '/project', + terminals: { sessions: new Map(), startChildProcess }, + } as unknown as ViteDevToolsNodeContext + return { context, startChildProcess } +} + describe('getBuildCommand', () => { it.each([false, true])('selects the project CLI with Vite+ installed: %s', async (vitePlus) => { const root = await mkdtemp(join(tmpdir(), 'devtools-build-')) @@ -26,7 +41,32 @@ describe('getBuildCommand', () => { command: vitePlus ? 'vp' : 'vite', args: ['build'], cwd, - env: { VITE_DEVTOOLS_ROLLDOWN: 'true' }, + env: { NODE_ENV: 'production', [ROLLDOWN_DEVTOOLS_ENV]: 'true' }, + }) + }) + + it('builds for production even though the dev server runs with NODE_ENV=development', () => { + const { context } = fakeContext() + vi.stubEnv('NODE_ENV', 'development') + // The dev server sets `NODE_ENV=development`, and the spawned build + // inherits the dev server's env. Vite keeps an already-set `NODE_ENV`, + // so the build must override it to get a production bundle. + expect(getBuildCommand(context)).toEqual({ + command: 'vite', + args: ['build'], + cwd: '/project', + env: { NODE_ENV: 'production', [ROLLDOWN_DEVTOOLS_ENV]: 'true' }, + }) + }) +}) + +describe('startBuild', () => { + it('spawns the build with the production NODE_ENV', async () => { + const { context, startChildProcess } = fakeContext() + await startBuild(context) + expect(startChildProcess).toHaveBeenCalledTimes(1) + expect(startChildProcess.mock.calls[0]![0]).toMatchObject({ + env: { NODE_ENV: 'production' }, }) }) }) diff --git a/packages/rolldown/src/node/rolldown/build-runner.ts b/packages/rolldown/src/node/rolldown/build-runner.ts index 55122ff1..fb50f728 100644 --- a/packages/rolldown/src/node/rolldown/build-runner.ts +++ b/packages/rolldown/src/node/rolldown/build-runner.ts @@ -45,7 +45,14 @@ export function getBuildCommand(context: ViteDevToolsNodeContext): DevToolsChild command: isVitePlusInstalled(cwd) ? 'vp' : 'vite', args: ['build'], cwd, - env: { [ROLLDOWN_DEVTOOLS_ENV]: 'true' }, + env: { + // The child inherits the dev server's env, where Vite has set + // `NODE_ENV=development`. `vite build` keeps an already-set `NODE_ENV`, + // which would keep every library's dev-only branches in the bundle, so + // pin what a plain `vite build` resolves to. + NODE_ENV: 'production', + [ROLLDOWN_DEVTOOLS_ENV]: 'true', + }, } }