使用Bun+Hono时serveStatic中间件返回404,但静态文件实际存在
解决Bun+Hono部署React静态资源404问题
修改后的完整服务器代码
import { Hono } from "hono"; import { cors } from "hono/cors"; import { serveStatic } from "hono/bun"; import path from "path"; import { fileURLToPath } from "url"; // 获取当前文件的绝对路径与目录,避免相对路径解析误差 const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const app = new Hono(); // CORS 配置 app.use( cors({ origin: ["http://localhost", "https://localhost"], allowMethods: ["GET", "POST"], exposeHeaders: ["Content-Type"], maxAge: 300, }) ); // 预解析两个前端项目的dist目录绝对路径 const linksDistDir = path.resolve(__dirname, "../dist/links"); const portfolioDistDir = path.resolve(__dirname, "../dist/portfolio"); // 静态资源路由配置(核心修复点) app.use("/assets/*", serveStatic({ root: linksDistDir })); app.use("/portfolio/assets/*", serveStatic({ root: portfolioDistDir })); // 主页与portfolio页面路由 app.get("/", serveStatic({ path: path.resolve(linksDistDir, "index.html") })); app.get("/portfolio", serveStatic({ path: path.resolve(portfolioDistDir, "index.html") })); // 可选:SPA刷新 fallback,处理React单页应用刷新子路由的404问题 app.get("*", (c) => { if (c.req.path.startsWith("/portfolio")) { return c.serveStatic(path.resolve(portfolioDistDir, "index.html")); } return c.serveStatic(path.resolve(linksDistDir, "index.html")); }); // 启动服务器 try { const server = Bun.serve({ fetch: app.fetch, port: process.env.PORT || 3000, }); console.log("Server started on port : ", server.port); } catch (e) { console.error("Error occured while starting the server : ", e); }
关键修复说明
- 绝对路径替代相对路径:用
import.meta.url结合path.resolve生成绝对路径,彻底解决因Bun启动目录不同导致的路径解析错误。相对路径../dist的解析依赖于启动命令的工作目录,绝对路径不受此影响。 - 修正serveStatic的root配置:原代码中
root: "../dist/links/assets/"会导致Hono尝试在../dist/links/assets/assets/下查找文件(因为路由/assets/*会拼接在root之后),自然返回404。正确的root应该是包含assets文件夹的上级目录(即dist/links),Hono会自动将路由/assets/*映射到root/assets/*对应的文件。 - SPA Fallback路由:如果是React单页应用,用户刷新
/portfolio这类子路由时,服务器需要返回对应项目的index.html,否则会出现404,该配置覆盖了这种场景。
额外检查项
- 确认
dist/links/assets和dist/portfolio/assets目录下存在编译后的静态文件(如js、css、图片等)。 - 检查前端React项目的资源路径配置:比如Vite中的
base或Create React App中的homepage,确保生成的资源路径与服务器路由匹配(比如主页资源路径为/assets/xxx,portfolio资源路径为/portfolio/assets/xxx)。
内容的提问来源于stack exchange,提问作者Sourabrata Bose
相关产品推荐
相关产品推荐

