app.static()需校验目录存在、避免中间件拦截、禁用于生产托管前端、并提前配置压缩与mime类型;否则将静默失败或返回404。

app.Static() 的基本用法和路径陷阱
直接用 app.Static("/static", "./public") 是最常见写法,但容易忽略两点:一是第二个参数必须是**文件系统上的真实相对或绝对路径**,不是 URL 路径;二是如果目录不存在,Fiber 不报错,但所有请求返回 404。比如你写成 app.Static("/static", "assets"),而当前工作目录下没有 assets/ 文件夹,就会静默失败。
建议在启动前加一行校验:
if _, err := os.Stat("./public"); os.IsNotExist(err) {
log.Fatal("static dir ./public not found")
}
另外,./public 中的点号不能省——写成 "public" 在某些运行环境下(如从其他目录执行 go run)会找不到路径。
避免中间件穿透导致静态资源被拦截
如果你注册了全局中间件(比如日志、JWT 验证),默认会作用于所有路由,包括 /static/*。这时候用户访问 /static/logo.png 可能被中间件拦下并返回 401 或 403。
解决方法是给 app.Static() 显式关闭中间件链:
- 用
app.Static("/static", "./public", fiber.Static{Next: func(c *fiber.Ctx) bool { return false }}) - 或者更推荐:把
app.Static()放在所有中间件 之前 注册,因为 Fiber 路由匹配是顺序优先的
注意:Next: func(c *fiber.Ctx) bool { return false } 这个函数返回 false 表示“不继续往下走中间件”,不是“跳过当前中间件”——这是初学者最容易反直觉的地方。
生产环境别用 Fiber 托管前端构建产物
虽然 app.Static() 能跑 HTML/CSS/JS,但它不支持 Cache-Control 智能缓存、Brotli 压缩、ETag 自动生成等生产必需能力。尤其是 Vue/React 构建出的 index.html 需要 fallback 到该文件(SPA 路由),Fiber 默认不提供 Index 或 Fallback 选项。
可行替代方案:
- 用 Nginx 做前置,把
/static/和/全部代理到index.html,Fiber 只负责 API - 如果坚持用 Fiber,得手动加一层兜底路由:
app.Get("*", func(c *fiber.Ctx) error { return c.SendFile("./public/index.html") }),但要注意它必须放在所有 API 路由之后,否则会吞掉所有请求
这个兜底逻辑一旦放错位置,整个 API 就不可达——没有错误提示,只有 404,排查起来特别隐蔽。
gzip 和 mime 类型需要额外配置
Fiber v2 默认不启用 gzip 压缩,静态文件返回时也按扩展名推断 Content-Type,但对 .webp、.woff2 等较新格式识别不准,可能返回 text/plain 导致浏览器拒绝加载。
补救方式:
- 启用压缩:传入
fiber.Static{Compress: true} - 自定义 MIME 类型映射:启动前调用
fiber.AddMissingMimeTypes(map[string]string{"webp": "image/webp", "woff2": "font/woff2"})
这两个配置都得在 app.Static() 调用前生效,晚了就不起作用。











