Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: serve static and public middlewares after restart #14895

Closed
Closed
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
6 changes: 2 additions & 4 deletions packages/vite/src/node/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -711,17 +711,15 @@ export async function _createServer(
// this applies before the transform middleware so that these files are served
// as-is without transforms.
if (config.publicDir) {
middlewares.use(
servePublicMiddleware(config.publicDir, config.server.headers),
)
middlewares.use(servePublicMiddleware(server))
}

// main transform middleware
middlewares.use(transformMiddleware(server))

// serve static files
middlewares.use(serveRawFsMiddleware(server))
middlewares.use(serveStaticMiddleware(root, server))
middlewares.use(serveStaticMiddleware(server))

// html fallback
if (config.appType === 'spa' || config.appType === 'mpa') {
Expand Down
59 changes: 41 additions & 18 deletions packages/vite/src/node/server/middlewares/static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import sirv from 'sirv'
import type { Connect } from 'dep-types/connect'
import escapeHtml from 'escape-html'
import type { ViteDevServer } from '../..'
import type { ResolvedConfig } from '../../config'
import { FS_PREFIX } from '../../constants'
import {
cleanUrl,
Expand Down Expand Up @@ -54,45 +55,50 @@ const sirvOptions = ({
}
}

export function servePublicMiddleware(
dir: string,
headers?: OutgoingHttpHeaders,
): Connect.NextHandleFunction {
const serve = sirv(
dir,
const getServePublic = createSirvCache((config: ResolvedConfig) => {
const {
publicDir,
server: { headers },
} = config
return sirv(
publicDir,
sirvOptions({
headers,
shouldServe: (filePath) => shouldServeFile(filePath, dir),
shouldServe: (filePath) => shouldServeFile(filePath, publicDir),
}),
)

})
export function servePublicMiddleware(
server: ViteDevServer,
): Connect.NextHandleFunction {
// Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`
return function viteServePublicMiddleware(req, res, next) {
// skip import request and internal requests `/@fs/ /@vite-client` etc...
if (isImportRequest(req.url!) || isInternalRequest(req.url!)) {
return next()
}
serve(req, res, next)
getServePublic(server.config)(req, res, next)
}
}

const getServeStatic = createSirvCache((config: ResolvedConfig) =>
sirv(
config.root,
sirvOptions({
headers: config.server.headers,
}),
),
)
export function serveStaticMiddleware(
dir: string,
server: ViteDevServer,
): Connect.NextHandleFunction {
const serve = sirv(
dir,
sirvOptions({
headers: server.config.server.headers,
}),
)

// Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`
return function viteServeStaticMiddleware(req, res, next) {
// only serve the file if it's not an html request or ends with `/`
// so that html requests can fallthrough to our html middleware for
// special processing
// also skip internal requests `/@fs/ /@vite-client` etc...
const dir = server.config.root
const cleanedUrl = cleanUrl(req.url!)
if (
cleanedUrl[cleanedUrl.length - 1] === '/' ||
Expand Down Expand Up @@ -141,7 +147,7 @@ export function serveStaticMiddleware(
req.url = url.href.slice(url.origin.length)
}

serve(req, res, next)
getServeStatic(server.config)(req, res, next)
}
}

Expand Down Expand Up @@ -255,3 +261,20 @@ function renderRestrictedErrorHTML(msg: string): string {
</body>
`
}

function createSirvCache(
createSirv: (config: ResolvedConfig) => Connect.NextHandleFunction,
) {
const serveStaticCache = new WeakMap<
ResolvedConfig,
Connect.NextHandleFunction
>()
return function getServeStatic(config: ResolvedConfig) {
let serveStatic = serveStaticCache.get(config)
if (!serveStatic) {
;(serveStatic = createSirv(config)),
serveStaticCache.set(config, serveStatic)
}
return serveStatic
}
}