本文说明当前静态资源重构后的设计边界、优先级以及推荐用法。
原有静态资源能力主要分为两类:
- 根包中的
Static/StaticFS/StaticFile/EmbedFS pkg/static中面向 ZIP 的RegisterZipFS/RegisterZipFile
这套能力能覆盖基本文件暴露场景,但在“前端站点兜底”“嵌入式 ZIP”“避免 catch-all 路由抢占业务路由”这几个高频需求上不够顺手。
本次重构的目标是:
- 区分“普通静态资源”和“前端站点”两类语义
- 让资源来源与路由挂载方式解耦
- 在不影响普通路由与 regex 路由的前提下提供站点兜底
与上游 Gin 对齐,直接注册普通路由。
适合:
- 明确的目录映射
- 单文件暴露
- 不需要 history fallback 的只读资源
表示“静态资源目录”语义。
适合:
- JS / CSS / 图片 / 字体 / 下载文件
- 管理后台资源目录
- 不希望未命中时自动落回首页的路径
特点:
- 通过
NoRoute受控兜底 - 文件未命中时直接放弃处理,不自动回退到
index.html
表示“前端站点”语义。
适合:
- SPA
- 后台控制台
- 前端构建产物托管
特点:
- 支持
index.html - 支持 history fallback
- 支持自定义
404.html - 同样通过
NoRoute受控兜底
表示“全站未命中时交给前端站点”。
适合:
- 前后端同服务部署
- 除
/api/*外全部交给前端路由 - 单页应用全局接管
当前统一支持以下来源:
- 本地目录
- 任意
http.FileSystem - ZIP 文件
- 嵌入式 ZIP
对应入口包括:
Assets/AssetsFS/AssetsZip/AssetsEmbeddedZipSite/SiteFS/SiteZip/SiteEmbeddedZipFallbackSite/FallbackSiteFS/FallbackSiteZip/FallbackSiteEmbeddedZip
为了避免静态站点挂载与业务路由互相冲突,当前顺序固定为:
- 普通 Gin 路由
- regex 路由
Assets*/Site*/FallbackSite*- 用户
NoRoute
这意味着:
SiteFS("/app", ...)不会抢/app/health这样的普通路由- regex 路由例如
/app/{id:[0-9]+}也会优先于站点兜底 FallbackSiteFS("/")更像“最终前端接管层”,而不是全局 catch-all 普通路由
- 命中具体文件则返回文件
- 命中目录时可返回目录下的
index.html - 文件不存在时直接放弃处理
- 命中具体文件则返回文件
- 命中目录时返回目录下的
index.html - 未命中且请求明确接受 HTML 时,可回退到首页
- 若配置了
WithNotFoundFile("404.html"),则在未命中时返回该文件
为了避免把普通 API 请求错误地回退到前端首页,history fallback 只在以下情况下生效:
- 请求方法为
GET或HEAD - 路径不带文件扩展名
Accept头显式包含text/html或application/xhtml+xml
NewZipFileSystem 仍然保留,适合:
- 运行时加载 ZIP 包
- 密码保护 ZIP
- 热更新 ZIP
新增 NewEmbeddedZipFS,适合:
- 单二进制分发
- 通过
embed.FS承载前端构建产物 ZIP - 不希望运行时依赖外部文件
当前嵌入式 ZIP 暂不支持密码保护。
WithIndexFile(...)WithHistoryFallback()WithoutHistoryFallback()WithNotFoundFile(...)
WithHotReload(...)WithPassword(...)WithSubPaths(...)WithStripPrefix(...)WithFallback(...)
其中 WithFallback(...) 用于“ZIP 文件系统不可用”时的回退,不等同于“文件未命中时的站点兜底”。
r.Assets("/assets", "./public")r.Site("/app", "./dist")e.FallbackSite("./dist")_ = r.SiteZip("/admin", "./admin.zip")_ = e.FallbackSiteEmbeddedZip(assets, "ui/app.zip")- 旧的
Static*/Embed*全部保留 pkg/static.RegisterZipFS/RegisterZipFile保留兼容- 新增
Assets*/Site*/FallbackSite*作为更高层、更安全的推荐入口