Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions packages/vite/src/node/__tests__/scan.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,35 @@ test('scan resolves build.rolldownOptions.input relative to the root', async (ct
})
})

// regression test for `The server is being restarted or closed. Request is outdated`
// error in the scanner. The dependency scanner runs in the background and
// may still be crawling when the server is closed. The scan fails because resolutions
// reject with `ERR_CLOSED_SERVER`, but this failure must be ignored (the scan result is
// discarded on close anyway) so it doesn't escape as an unhandled rejection.
test('scan ignores the failure when the server is closed mid-scan', async (ctx) => {
const server = await createServer({
configFile: false,
logLevel: 'silent',
root: path.join(import.meta.dirname, 'fixtures', 'scan-build-input', 'src'),
optimizeDeps: {
entries: ['./entry-client.tsx'],
force: true,
noDiscovery: false,
},
})
ctx.onTestFinished(() => server.close())

// Simulate the server being torn down while the scanner is still running.
await server.environments.client.pluginContainer.close()

const { cancel, result } = scanImports(
devToScanEnvironment(server.environments.client),
)
ctx.onTestFinished(cancel)

await expect(result).resolves.toEqual({ deps: {}, missing: {} })
})

test('scan import.meta.glob package imports patterns', async (ctx) => {
const server = await createServer({
configFile: false,
Expand Down
16 changes: 15 additions & 1 deletion packages/vite/src/node/optimizer/scan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ import {
virtualModuleRE,
} from '../utils'
import type { EnvironmentPluginContainer } from '../server/pluginContainer'
import { createEnvironmentPluginContainer } from '../server/pluginContainer'
import {
ERR_CLOSED_SERVER,
createEnvironmentPluginContainer,
} from '../server/pluginContainer'
import { BaseEnvironment } from '../baseEnvironment'
import type { DevEnvironment } from '../server/environment'
import { transformGlobImport } from '../plugins/importMetaGlob'
Expand Down Expand Up @@ -165,6 +168,17 @@ export function scanImports(environment: ScanEnvironment): {
missing,
}
} catch (e) {
// The scanner runs in the background and may still be crawling when the
// server is closed. In that case resolutions reject with
// `ERR_CLOSED_SERVER` and the scan build fails.
if (
e.errors?.some(
(error: { pluginCode?: string }) =>
error.pluginCode === ERR_CLOSED_SERVER,
)
) {
return
}
const prependMessage = colors.red(`\
Failed to scan for dependencies from entries:
${entries.join('\n')}
Expand Down
Loading