-
-
Notifications
You must be signed in to change notification settings - Fork 6.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(html)!: align html serving between dev and preview (#14756)
Co-authored-by: 翠 / green <[email protected]>
- Loading branch information
1 parent
a090742
commit 4f71ae8
Showing
21 changed files
with
236 additions
and
114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 73 additions & 35 deletions
108
packages/vite/src/node/server/middlewares/htmlFallback.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,48 +1,86 @@ | ||
import fs from 'node:fs' | ||
import path from 'node:path' | ||
import history from 'connect-history-api-fallback' | ||
import type { Connect } from 'dep-types/connect' | ||
import { createDebugger } from '../../utils' | ||
import { cleanUrl, createDebugger } from '../../utils' | ||
|
||
const debug = createDebugger('vite:html-fallback') | ||
|
||
export function htmlFallbackMiddleware( | ||
root: string, | ||
spaFallback: boolean, | ||
mounted = false, | ||
): Connect.NextHandleFunction { | ||
const historyHtmlFallbackMiddleware = history({ | ||
disableDotRule: true, | ||
logger: createDebugger('vite:html-fallback'), | ||
rewrites: [ | ||
// support /dir/ without explicit index.html | ||
{ | ||
from: /\/$/, | ||
to({ parsedUrl, request }: any) { | ||
const rewritten = | ||
decodeURIComponent(parsedUrl.pathname) + 'index.html' | ||
|
||
if (fs.existsSync(path.join(root, rewritten))) { | ||
return rewritten | ||
} | ||
|
||
return spaFallback ? `/index.html` : request.url | ||
}, | ||
}, | ||
{ | ||
from: /\.html$/, | ||
to({ parsedUrl, request }: any) { | ||
// .html files are not handled by serveStaticMiddleware | ||
// so we need to check if the file exists | ||
const pathname = decodeURIComponent(parsedUrl.pathname) | ||
if (fs.existsSync(path.join(root, pathname))) { | ||
return request.url | ||
} | ||
return spaFallback ? `/index.html` : request.url | ||
}, | ||
}, | ||
], | ||
}) | ||
// When this middleware is mounted on a route, we need to re-assign `req.url` with a | ||
// leading `.` to signal a relative rewrite. Returning with a leading `/` returns a | ||
// buggy `req.url`. e.g.: | ||
// | ||
// mount /foo/bar: | ||
// req.url = /index.html | ||
// final = /foo/barindex.html | ||
// | ||
// mount /foo/bar: | ||
// req.url = ./index.html | ||
// final = /foo/bar/index.html | ||
const prepend = mounted ? '.' : '' | ||
|
||
// Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...` | ||
return function viteHtmlFallbackMiddleware(req, res, next) { | ||
return historyHtmlFallbackMiddleware(req, res, next) | ||
if ( | ||
// Only accept GET or HEAD | ||
(req.method !== 'GET' && req.method !== 'HEAD') || | ||
// Require Accept header | ||
!req.headers || | ||
typeof req.headers.accept !== 'string' || | ||
// Ignore JSON requests | ||
req.headers.accept.includes('application/json') || | ||
// Require Accept: text/html or */* | ||
!( | ||
req.headers.accept.includes('text/html') || | ||
req.headers.accept.includes('*/*') | ||
) | ||
) { | ||
return next() | ||
} | ||
|
||
const url = cleanUrl(req.url!) | ||
const pathname = decodeURIComponent(url) | ||
|
||
// .html files are not handled by serveStaticMiddleware | ||
// so we need to check if the file exists | ||
if (pathname.endsWith('.html')) { | ||
const filePath = path.join(root, pathname) | ||
if (fs.existsSync(filePath)) { | ||
debug?.(`Rewriting ${req.method} ${req.url} to ${url}`) | ||
req.url = prepend + url | ||
return next() | ||
} | ||
} | ||
// trailing slash should check for fallback index.html | ||
else if (pathname[pathname.length - 1] === '/') { | ||
const filePath = path.join(root, pathname, 'index.html') | ||
if (fs.existsSync(filePath)) { | ||
const newUrl = url + 'index.html' | ||
debug?.(`Rewriting ${req.method} ${req.url} to ${newUrl}`) | ||
req.url = prepend + newUrl | ||
return next() | ||
} | ||
} | ||
// non-trailing slash should check for fallback .html | ||
else { | ||
const filePath = path.join(root, pathname + '.html') | ||
if (fs.existsSync(filePath)) { | ||
const newUrl = url + '.html' | ||
debug?.(`Rewriting ${req.method} ${req.url} to ${newUrl}`) | ||
req.url = prepend + newUrl | ||
return next() | ||
} | ||
} | ||
|
||
if (spaFallback) { | ||
debug?.(`Rewriting ${req.method} ${req.url} to /index.html`) | ||
req.url = prepend + '/index.html' | ||
} | ||
|
||
next() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import type { Connect } from 'dep-types/connect' | ||
|
||
export function notFoundMiddleware(): Connect.NextHandleFunction { | ||
// Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...` | ||
return function vite404Middleware(_, res) { | ||
res.statusCode = 404 | ||
res.end() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.