Skip to content

Commit cd5db66

Browse files
hi-ogawaclaude
andauthored
fix: replace default ssr environment runner with Vitest server module runner (#9506)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 59ea27c commit cd5db66

File tree

8 files changed

+68
-3
lines changed

8 files changed

+68
-3
lines changed

packages/vitest/src/node/core.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { getTasks, hasFailed, limitConcurrency } from '@vitest/runner/utils'
2020
import { SnapshotManager } from '@vitest/snapshot/manager'
2121
import { deepClone, deepMerge, nanoid, noop, toArray } from '@vitest/utils/helpers'
2222
import { join, normalize, relative } from 'pathe'
23+
import { isRunnableDevEnvironment } from 'vite'
2324
import { version } from '../../package.json' with { type: 'json' }
2425
import { WebSocketReporter } from '../api/setup'
2526
import { distDir } from '../paths'
@@ -247,6 +248,21 @@ export class Vitest {
247248
this._fetcher,
248249
resolved,
249250
)
251+
// patch default ssr runnable environment so third-party usage of `runner.import`
252+
// still works with Vite's external/noExternal configuration.
253+
const ssrEnvironment = server.environments.ssr
254+
if (isRunnableDevEnvironment(ssrEnvironment)) {
255+
const ssrRunner = new ServerModuleRunner(
256+
ssrEnvironment,
257+
this._fetcher,
258+
resolved,
259+
)
260+
Object.defineProperty(ssrEnvironment, 'runner', {
261+
value: ssrRunner,
262+
writable: true,
263+
configurable: true,
264+
})
265+
}
250266

251267
if (this.config.watch) {
252268
// hijack server restart

packages/vitest/src/node/plugins/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,6 @@ export async function VitestPlugin(
260260
}
261261
},
262262
configureServer: {
263-
// runs after vite:import-analysis as it relies on `server` instance on Vite 5
264-
order: 'post',
265263
async handler(server) {
266264
if (options.watch && process.env.VITE_TEST_WATCHER_DEBUG) {
267265
server.watcher.on('ready', () => {

packages/vitest/src/node/plugins/workspace.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,6 @@ export function WorkspaceVitestPlugin(
242242
},
243243
{
244244
name: 'vitest:project:server',
245-
enforce: 'post',
246245
async configureServer(server) {
247246
const options = deepMerge({}, configDefaults, server.config.test || {})
248247
await project._configureServer(options, server)

packages/vitest/src/node/project.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { deepMerge, nanoid, slash } from '@vitest/utils/helpers'
2323
import { isAbsolute, join, relative } from 'pathe'
2424
import pm from 'picomatch'
2525
import { glob } from 'tinyglobby'
26+
import { isRunnableDevEnvironment } from 'vite'
2627
import { setup } from '../api/setup'
2728
import { createDefinesScript } from '../utils/config-helpers'
2829
import { NativeModuleRunner } from '../utils/nativeModuleRunner'
@@ -579,6 +580,20 @@ export class TestProject {
579580
this._fetcher,
580581
this._config,
581582
)
583+
584+
const ssrEnvironment = server.environments.ssr
585+
if (isRunnableDevEnvironment(ssrEnvironment)) {
586+
const ssrRunner = new ServerModuleRunner(
587+
ssrEnvironment,
588+
this._fetcher,
589+
this._config,
590+
)
591+
Object.defineProperty(ssrEnvironment, 'runner', {
592+
value: ssrRunner,
593+
writable: true,
594+
configurable: true,
595+
})
596+
}
582597
}
583598

584599
/** @internal */
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { test, expect } from 'vitest'
2+
3+
test('basic', () => {
4+
expect(1 + 1).toBe(2)
5+
})
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import * as vite from 'vite'
2+
export default vite
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import assert from 'node:assert'
2+
import { isRunnableDevEnvironment, createServer } from 'vite'
3+
import { defineConfig } from 'vitest/config'
4+
5+
export default defineConfig({
6+
plugins: [
7+
{
8+
name: 'test-ssr-runner',
9+
// test ssr runner.import() with correct external semantics in configureServer hook
10+
// vite should be externalized and reference-equal to the directly imported one
11+
async configureServer(server) {
12+
const ssr = server.environments.ssr
13+
if (isRunnableDevEnvironment(ssr)) {
14+
const m = await ssr.runner.import<{ default: typeof import("vite") }>('./test-runner.js')
15+
assert(m.default.createServer === createServer)
16+
;(globalThis as any).__testSsrRunner = m.default.version
17+
}
18+
},
19+
},
20+
],
21+
})

test/cli/test/ssr-runner.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { version } from 'vite'
2+
import { expect, it } from 'vitest'
3+
import { runVitest } from '../../test-utils'
4+
5+
// https://github.com/vitest-dev/vitest/issues/9324
6+
it('ssr runner.import() works in configureServer', async () => {
7+
await runVitest({ root: './fixtures/ssr-runner' })
8+
expect((globalThis as any).__testSsrRunner).toBe(version)
9+
})

0 commit comments

Comments
 (0)