修掉资源 404 被当成页面返回的 bug;加一条命令起开发模式

单页应用的兜底原本对任何找不到的路径都回 index.html,包括带扩展名的资源。
资源文件是带哈希的,每次打包换名字,浏览器缓存了旧 index.html 时会去请求一个已经
不存在的 .js,然后拿到一份 HTML,报出「MIME 类型不对」——一句完全指不到病根的错误。
现在带扩展名的路径找不到就回 404,index.html 也不再允许缓存。

另外 dev:all 一条命令同时起后端(--hot)和前端(Vite),省掉记两个终端和两个端口。
This commit is contained in:
im0o
2026-08-10 14:15:22 +08:00
parent 860da5d28f
commit 6029eacf50
4 changed files with 64 additions and 10 deletions
+26 -4
View File
@@ -61,15 +61,37 @@ const WEB_DIST = new URL('../web-dist/', import.meta.url).pathname.replace(/^\/(
/**
* 静态文件不需要令牌——它们只是一个空壳,所有数据都要带令牌才拿得到。
* 单页应用的路由由前端接管,所以找不到的路径一律回 index.html。
*
* 单页应用的路由由前端接管,所以找不到的路径回 index.html。但这条**不能**用在
* 带扩展名的路径上:资源文件是带哈希的,每次打包都换名字,浏览器要是缓存了旧的
* index.html,它引用的那个 .js 就已经不存在了。这时候回 index.html 等于把一份 HTML
* 当作 JavaScript 交给浏览器,报出来的是「MIME 类型不对」——一句完全指不到病根的错误。
* 老老实实回 404,浏览器才会重新去取 index.html。
*/
const HAS_EXTENSION = /\.[a-z0-9]+$/i
async function serveStatic(path: string): Promise<Response> {
const shellHeaders = {
'Content-Type': 'text/html; charset=utf-8',
// 空壳不缓存,否则打包后旧的 index.html 会一直引用已经不存在的资源
'Cache-Control': 'no-cache',
}
const target = Bun.file(WEB_DIST + (path === '/' ? 'index.html' : path.slice(1)))
if (await target.exists()) return new Response(target)
if (await target.exists()) {
return path === '/' ? new Response(target, { headers: shellHeaders }) : new Response(target)
}
if (HAS_EXTENSION.test(path)) {
return new Response(`找不到 ${path}`, {
status: 404,
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
})
}
const shell = Bun.file(`${WEB_DIST}index.html`)
if (await shell.exists()) return new Response(shell)
return new Response('前端还没打包。先运行 bun run build,或者开发时用 bun run dev:web。', {
if (await shell.exists()) return new Response(shell, { headers: shellHeaders })
return new Response('前端还没打包。运行 bun run build,或者开发时用 bun run dev:web。', {
status: 404,
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
})