diff --git a/packages/vite/src/node/publicDir.ts b/packages/vite/src/node/publicDir.ts index f2055fff8afb9d..8458579e378137 100644 --- a/packages/vite/src/node/publicDir.ts +++ b/packages/vite/src/node/publicDir.ts @@ -2,6 +2,7 @@ import fs from 'node:fs' import path from 'node:path' import type { ResolvedConfig } from './config' import { + ERR_SYMLINK_IN_RECURSIVE_READDIR, cleanUrl, normalizePath, recursiveReaddir, @@ -12,8 +13,16 @@ const publicFilesMap = new WeakMap>() export async function initPublicFiles( config: ResolvedConfig, -): Promise> { - const fileNames = await recursiveReaddir(config.publicDir) +): Promise | undefined> { + let fileNames: string[] + try { + fileNames = await recursiveReaddir(config.publicDir) + } catch (e) { + if (e.code === ERR_SYMLINK_IN_RECURSIVE_READDIR) { + return + } + throw e + } const publicFiles = new Set( fileNames.map((fileName) => fileName.slice(config.publicDir.length)), ) diff --git a/packages/vite/src/node/server/index.ts b/packages/vite/src/node/server/index.ts index 2b799dbfd2b8e7..b2632c841ca0ef 100644 --- a/packages/vite/src/node/server/index.ts +++ b/packages/vite/src/node/server/index.ts @@ -645,7 +645,7 @@ export async function _createServer( file = normalizePath(file) await container.watchChange(file, { event: isUnlink ? 'delete' : 'create' }) - if (config.publicDir && file.startsWith(config.publicDir)) { + if (publicFiles && config.publicDir && file.startsWith(config.publicDir)) { publicFiles[isUnlink ? 'delete' : 'add']( file.slice(config.publicDir.length), ) diff --git a/packages/vite/src/node/server/middlewares/static.ts b/packages/vite/src/node/server/middlewares/static.ts index 57f995d8e1b0f8..dde6842aa95533 100644 --- a/packages/vite/src/node/server/middlewares/static.ts +++ b/packages/vite/src/node/server/middlewares/static.ts @@ -54,7 +54,7 @@ const sirvOptions = ({ export function servePublicMiddleware( server: ViteDevServer, - publicFiles: Set, + publicFiles?: Set, ): Connect.NextHandleFunction { const dir = server.config.publicDir const serve = sirv( @@ -82,7 +82,7 @@ export function servePublicMiddleware( // in-memory set of known public files. This set is updated on restarts. // also skip import request and internal requests `/@fs/ /@vite-client` etc... if ( - !publicFiles.has(toFilePath(req.url!)) || + (publicFiles && !publicFiles.has(toFilePath(req.url!))) || isImportRequest(req.url!) || isInternalRequest(req.url!) ) { diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 395568978662ce..ff23df8a6d3e30 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -623,6 +623,8 @@ export function copyDir(srcDir: string, destDir: string): void { } } +export const ERR_SYMLINK_IN_RECURSIVE_READDIR = + 'ERR_SYMLINK_IN_RECURSIVE_READDIR' export async function recursiveReaddir(dir: string): Promise { if (!fs.existsSync(dir)) { return [] @@ -637,6 +639,13 @@ export async function recursiveReaddir(dir: string): Promise { } throw e } + if (dirents.some((dirent) => dirent.isSymbolicLink())) { + const err: any = new Error( + 'Symbolic links are not supported in recursiveReaddir', + ) + err.code = ERR_SYMLINK_IN_RECURSIVE_READDIR + throw err + } const files = await Promise.all( dirents.map((dirent) => { const res = path.resolve(dir, dirent.name)