Skip to content

Commit e2e11b1

Browse files
authored
fix(module-runner): allow already resolved id as entry (#19768)
1 parent 7200dee commit e2e11b1

File tree

6 files changed

+74
-28
lines changed

6 files changed

+74
-28
lines changed

packages/vite/src/node/plugins/importAnalysis.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export function isExplicitImportRequired(url: string): boolean {
100100
return !isJSRequest(url) && !isCSSRequest(url)
101101
}
102102

103-
export function normalizeResolvedIdToUrl(
103+
function normalizeResolvedIdToUrl(
104104
environment: DevEnvironment,
105105
url: string,
106106
resolved: PartialResolvedId,

packages/vite/src/node/ssr/__tests__/ssrLoadModule.spec.ts

-3
Original file line numberDiff line numberDiff line change
@@ -367,9 +367,6 @@ test('buildStart before transform', async () => {
367367
[
368368
"resolveId",
369369
],
370-
[
371-
"resolveId",
372-
],
373370
[
374371
"load",
375372
],

packages/vite/src/node/ssr/fetchModule.ts

-11
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
} from '../../shared/constants'
1111
import { genSourceMapUrl } from '../server/sourcemap'
1212
import type { DevEnvironment } from '../server/environment'
13-
import { normalizeResolvedIdToUrl } from '../plugins/importAnalysis'
1413

1514
export interface FetchModuleOptions {
1615
cached?: boolean
@@ -78,16 +77,6 @@ export async function fetchModule(
7877
return { externalize: file, type }
7978
}
8079

81-
// this is an entry point module, very high chance it's not resolved yet
82-
// for example: runner.import('./some-file') or runner.import('/some-file')
83-
if (isFileUrl || !importer) {
84-
const resolved = await environment.pluginContainer.resolveId(url)
85-
if (!resolved) {
86-
throw new Error(`[vite] cannot find entry point module '${url}'.`)
87-
}
88-
url = normalizeResolvedIdToUrl(environment, url, resolved)
89-
}
90-
9180
url = unwrapId(url)
9281

9382
const mod = await environment.moduleGraph.ensureEntryFromUrl(url)

packages/vite/src/node/ssr/runtime/__tests__/server-runtime.spec.ts

+64-10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { existsSync, readdirSync } from 'node:fs'
22
import { posix, win32 } from 'node:path'
33
import { fileURLToPath } from 'node:url'
4-
import { describe, expect } from 'vitest'
4+
import { describe, expect, vi } from 'vitest'
55
import { isWindows } from '../../../../shared/utils'
66
import { createModuleRunnerTester } from './utils'
77

@@ -29,17 +29,36 @@ describe('module runner initialization', async () => {
2929
const mod = await runner.import('virtual:test')
3030
expect(mod.msg).toBe('virtual')
3131

32-
// virtual module query is not supported out of the box
33-
// (`?t=...` was working on Vite 5 ssrLoadModule as `transformRequest` strips off timestamp query)
34-
await expect(() =>
35-
runner.import(`virtual:test?t=${Date.now()}`),
36-
).rejects.toMatchObject({
37-
message: expect.stringContaining('cannot find entry point module'),
38-
})
32+
// already resolved id works similar to `transformRequest`
33+
expect(await runner.import(`\0virtual:normal`)).toMatchInlineSnapshot(`
34+
{
35+
"default": "ok",
36+
}
37+
`)
38+
39+
// escaped virtual module id works
40+
expect(await runner.import(`/@id/__x00__virtual:normal`))
41+
.toMatchInlineSnapshot(`
42+
{
43+
"default": "ok",
44+
}
45+
`)
46+
47+
// timestamp query works
48+
expect(await runner.import(`virtual:normal?t=${Date.now()}`))
49+
.toMatchInlineSnapshot(`
50+
{
51+
"default": "ok",
52+
}
53+
`)
54+
55+
// other arbitrary queries don't work
3956
await expect(() =>
40-
runner.import('virtual:test?abcd=1234'),
57+
runner.import('virtual:normal?abcd=1234'),
4158
).rejects.toMatchObject({
42-
message: expect.stringContaining('cannot find entry point module'),
59+
message: expect.stringContaining(
60+
'Failed to load url virtual:normal?abcd=1234',
61+
),
4362
})
4463
})
4564

@@ -338,3 +357,38 @@ describe('resolveId absolute path entry', async () => {
338357
expect(mod.name).toMatchInlineSnapshot(`"virtual:basic"`)
339358
})
340359
})
360+
361+
describe('virtual module hmr', async () => {
362+
let state = 'init'
363+
364+
const it = await createModuleRunnerTester({
365+
plugins: [
366+
{
367+
name: 'test-resolevId',
368+
enforce: 'pre',
369+
resolveId(source) {
370+
if (source === 'virtual:test') {
371+
return '\0' + source
372+
}
373+
},
374+
load(id) {
375+
if (id === '\0virtual:test') {
376+
return `export default ${JSON.stringify(state)}`
377+
}
378+
},
379+
},
380+
],
381+
})
382+
383+
it('full reload', async ({ server, runner }) => {
384+
const mod = await runner.import('virtual:test')
385+
expect(mod.default).toBe('init')
386+
state = 'reloaded'
387+
server.environments.ssr.moduleGraph.invalidateAll()
388+
server.environments.ssr.hot.send({ type: 'full-reload' })
389+
await vi.waitFor(() => {
390+
const mod = runner.evaluatedModules.getModuleById('\0virtual:test')
391+
expect(mod?.exports.default).toBe('reloaded')
392+
})
393+
})
394+
})

packages/vite/src/node/ssr/runtime/__tests__/utils.ts

+6
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ export async function createModuleRunnerTester(
6161
if (id === 'virtual:test') {
6262
return 'virtual:test'
6363
}
64+
if (id === 'virtual:normal') {
65+
return '\0' + id
66+
}
6467
},
6568
load(id) {
6669
if (id === `\0virtual:test`) {
@@ -69,6 +72,9 @@ export async function createModuleRunnerTester(
6972
if (id === `virtual:test`) {
7073
return `export const msg = 'virtual'`
7174
}
75+
if (id === '\0virtual:normal') {
76+
return 'export default "ok"'
77+
}
7278
},
7379
},
7480
...(config.plugins ?? []),

playground/hmr-ssr/__tests__/hmr-ssr.spec.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ if (!isBuild) {
250250

251251
describe('self accept with different entry point formats', () => {
252252
test.each(['./unresolved.ts', './unresolved', '/unresolved'])(
253-
'accepts if entry point is relative to root',
253+
'accepts if entry point is relative to root %s',
254254
async (entrypoint) => {
255255
await setupModuleRunner(entrypoint, {}, '/unresolved.ts')
256256

@@ -270,7 +270,7 @@ if (!isBuild) {
270270
'foo was: 1',
271271
'(self-accepting 1) foo is now: 2',
272272
'(self-accepting 2) foo is now: 2',
273-
updated('/unresolved.ts'),
273+
updated(entrypoint),
274274
],
275275
true,
276276
)
@@ -285,7 +285,7 @@ if (!isBuild) {
285285
'foo was: 2',
286286
'(self-accepting 1) foo is now: 3',
287287
'(self-accepting 2) foo is now: 3',
288-
updated('/unresolved.ts'),
288+
updated(entrypoint),
289289
],
290290
true,
291291
)

0 commit comments

Comments
 (0)