diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index 7b4107c8aafe05..1933a5484b7565 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -2,6 +2,7 @@ import fs from 'node:fs' import fsp from 'node:fs/promises' import path from 'node:path' import { pathToFileURL } from 'node:url' +import { promisify } from 'node:util' import { performance } from 'node:perf_hooks' import { createRequire } from 'node:module' import colors from 'picocolors' @@ -69,6 +70,7 @@ import type { ResolvedSSROptions, SSROptions } from './ssr' import { resolveSSROptions } from './ssr' const debug = createDebugger('vite:config') +const promisifiedRealpath = promisify(fs.realpath) export type { RenderBuiltAssetUrl, @@ -1106,7 +1108,11 @@ async function loadConfigFromBundledFile( // for cjs, we can register a custom loader via `_require.extensions` else { const extension = path.extname(fileName) - const realFileName = await fsp.realpath(fileName) + // We don't use fsp.realpath() here because it has the same behaviour as + // fs.realpath.native. On some Windows systems, it returns uppercase volume + // letters (e.g. "C:\") while the Node.js loader uses lowercase volume letters. + // See https://github.com/vitejs/vite/issues/12923 + const realFileName = await promisifiedRealpath(fileName) const loaderExt = extension in _require.extensions ? extension : '.js' const defaultLoader = _require.extensions[loaderExt]! _require.extensions[loaderExt] = (module: NodeModule, filename: string) => {