You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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,该配置覆盖了这种场景。

额外检查项

  1. 确认dist/links/assets和dist/portfolio/assets目录下存在编译后的静态文件(如js、css、图片等)。
  2. 检查前端React项目的资源路径配置:比如Vite中的base或Create React App中的homepage,确保生成的资源路径与服务器路由匹配(比如主页资源路径为/assets/xxx,portfolio资源路径为/portfolio/assets/xxx)。

内容的提问来源于stack exchange,提问作者Sourabrata Bose

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 02:24:51