Revel 的静态资源默认放在与 app/、conf/ 同级的 public/ 目录下,框架自动注册 GET /public/*filepath 路由映射到该目录,不可随意移动或重命名。

Revel 的静态资源默认放哪?
Revel 约定:所有静态资源(CSS、JS、图片等)必须放在 public/ 目录下,且该目录需与 app/、conf/ 同级。这是硬性路径,不能靠配置“改名”或“移走”——框架启动时会自动注册 GET /public/*filepath 路由,把请求映射到 public/ 子路径。
常见错误现象:404 访问 /public/css/style.css,但文件明明存在。原因通常是:
-
public/放在了app/里面(比如app/public/),导致 Revel 找不到 - 用
http.FileServer直接挂载public/,绕过了 Revel 的路由机制,导致 filter(如压缩、ETag、缓存头)全部失效 - 部署时没把
public/目录一起打包或同步到服务器
怎么让静态资源走 Revel 路由而不是直连文件系统?
必须确保所有静态资源请求都经过 Revel 的 GET /public/*filepath 路由,否则拦截器、压缩、缓存控制等逻辑不会触发。关键点是:
- 不要在
main.go或init.go中手动调用http.Handle("/public/", ...) - 确认
conf/routes文件里有这行(Revel 默认自带,别删):GET /public/*filepath Static.Serve - 如果用了 Nginx 反向代理,不要在 Nginx 里配
location /public/去直接服务文件;应让所有请求透传给 Revel 进程,由它内部处理
否则你会失去 Cache-Control 设置、Gzip 压缩、甚至版本化 URL(如 ?v=abc123)的能力。
如何支持子路径部署(如部署到 /myapp/)?
Revel 本身不自动适配子路径前缀,静态资源 URL 会变成 /myapp/public/css/style.css,但默认路由只匹配 /public/...。解决方法只有两个:
- 改 Nginx 配置,在反代时 rewrite 路径(推荐):
location /myapp/public/ { rewrite ^/myapp(/public/.*)$ $1 break; proxy_pass http://127.0.0.1:8089; } - 修改
conf/routes,把路由改成GET /myapp/public/*filepath Static.Serve,并确保所有模板中引用的路径也带/myapp前缀(不推荐,维护成本高)
注意:Static.Serve 是 Revel 内置控制器,它依赖 filepath 参数做路径拼接,所以任何自定义前缀都必须和路由定义、模板 URL、Nginx rewrite 三者严格对齐。
为什么加了版本参数(?v=xxx)还是没生效?
常见原因是浏览器或 CDN 缓存了无参 URL(如 /public/js/app.js),而你只改了带参版本。Revel 的版本注入方案(如通过 resourceVersion 注入模板变量)只影响 HTML 模板生成的 URL,但无法强制旧 URL 失效。
真正起效的前提是:
- HTML 中所有静态资源链接都统一用模板变量拼接,例如:
<script src="/public/js/app.js?v=%7B%7B.resourceVersion%7D%7D"></script> - 确保每次构建或发布时,
app.conf中的resourceVersion确实变更(如设为 Git commit SHA) - CDN 或反向代理(如 Nginx)没有配置成忽略查询参数缓存(检查是否含
cache_key $scheme$request_method$host$request_uri,其中$request_uri包含参数)
最容易被忽略的是:开发时反复刷新页面,浏览器可能从内存缓存直接返回旧 JS,连网络请求都不发——强制 Cmd+Shift+R(macOS)或清空缓存再试。











