Skip to content

Commit 5451a34

Browse files
authored
fix(ssr): improve missing file error (#10880)
1 parent 828eeca commit 5451a34

File tree

5 files changed

+48
-14
lines changed

5 files changed

+48
-14
lines changed

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { parse as parseJS } from 'acorn'
99
import type { Node } from 'estree'
1010
import { findStaticImports, parseStaticImport } from 'mlly'
1111
import { makeLegalIdentifier } from '@rollup/pluginutils'
12-
import { getDepOptimizationConfig } from '..'
1312
import type { ViteDevServer } from '..'
1413
import {
1514
CLIENT_DIR,
@@ -44,6 +43,7 @@ import {
4443
unwrapId,
4544
wrapId
4645
} from '../utils'
46+
import { getDepOptimizationConfig } from '../config'
4747
import type { ResolvedConfig } from '../config'
4848
import type { Plugin } from '../plugin'
4949
import {
@@ -712,7 +712,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
712712
// These requests will also be registered in transformRequest to be awaited
713713
// by the deps optimizer
714714
if (config.server.preTransformRequests && staticImportedUrls.size) {
715-
staticImportedUrls.forEach(({ url, id }) => {
715+
staticImportedUrls.forEach(({ url }) => {
716716
url = removeImportQuery(url)
717717
transformRequest(url, server, { ssr }).catch((e) => {
718718
if (e?.code === ERR_OUTDATED_OPTIMIZED_DEP) {

packages/vite/src/node/server/middlewares/transform.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
unwrapId
1919
} from '../../utils'
2020
import { send } from '../send'
21-
import { transformRequest } from '../transformRequest'
21+
import { ERR_LOAD_URL, transformRequest } from '../transformRequest'
2222
import { isHTMLProxy } from '../../plugins/html'
2323
import {
2424
DEP_VERSION_RE,
@@ -224,6 +224,10 @@ export function transformMiddleware(
224224
// error but a normal part of the missing deps discovery flow
225225
return
226226
}
227+
if (e?.code === ERR_LOAD_URL) {
228+
// Let other middleware handle if we can't load the url via transformRequest
229+
return next()
230+
}
227231
return next(e)
228232
}
229233

packages/vite/src/node/server/transformRequest.ts

+14-11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import { getDepsOptimizer } from '../optimizer'
2121
import { injectSourcesContent } from './sourcemap'
2222
import { isFileServingAllowed } from './middlewares/static'
2323

24+
export const ERR_LOAD_URL = 'ERR_LOAD_URL'
25+
export const ERR_LOAD_PUBLIC_URL = 'ERR_LOAD_PUBLIC_URL'
26+
2427
const debugLoad = createDebugger('vite:load')
2528
const debugTransform = createDebugger('vite:transform')
2629
const debugCache = createDebugger('vite:cache')
@@ -215,18 +218,18 @@ async function loadAndTransform(
215218
}
216219
}
217220
if (code == null) {
218-
if (checkPublicFile(url, config)) {
219-
throw new Error(
220-
`Failed to load url ${url} (resolved id: ${id}). ` +
221-
`This file is in /public and will be copied as-is during build without ` +
222-
`going through the plugin transforms, and therefore should not be ` +
223-
`imported from source code. It can only be referenced via HTML tags.`
224-
)
225-
} else {
226-
return null
227-
}
221+
const isPublicFile = checkPublicFile(url, config)
222+
const msg = isPublicFile
223+
? `This file is in /public and will be copied as-is during build without ` +
224+
`going through the plugin transforms, and therefore should not be ` +
225+
`imported from source code. It can only be referenced via HTML tags.`
226+
: `Does the file exist?`
227+
const err: any = new Error(
228+
`Failed to load url ${url} (resolved id: ${id}). ${msg}`
229+
)
230+
err.code = isPublicFile ? ERR_LOAD_PUBLIC_URL : ERR_LOAD_URL
231+
throw err
228232
}
229-
230233
// ensure module in graph after successful load
231234
const mod = await moduleGraph.ensureEntryFromUrl(url, ssr)
232235
ensureWatchedFile(watcher, mod.file, root)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// eslint-disable-next-line node/no-missing-import
2+
import { foo } from './non-existent.js'
3+
4+
export const hello = 'world'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { fileURLToPath } from 'node:url'
2+
import { expect, test } from 'vitest'
3+
import { createServer } from '../../server'
4+
5+
const root = fileURLToPath(new URL('./', import.meta.url))
6+
7+
async function createDevServer() {
8+
const server = await createServer({ configFile: false, root })
9+
server.pluginContainer.buildStart({})
10+
return server
11+
}
12+
13+
test('ssrLoad', async () => {
14+
expect.assertions(1)
15+
const server = await createDevServer()
16+
try {
17+
await server.ssrLoadModule('/fixtures/modules/has-invalid-import.js')
18+
} catch (e) {
19+
expect(e.message).toBe(
20+
'Failed to load url ./non-existent.js (resolved id: ./non-existent.js). Does the file exist?'
21+
)
22+
}
23+
})

0 commit comments

Comments
 (0)