静态文件默认无缓存头,导致浏览器频繁发304请求;应为哈希命名资源用e.file()显式设cache-control,html则用短缓存或etag协商,中间件需校验路径前缀和200状态码。

静态文件默认不带 Cache-Control,浏览器每次重验
Echo 的 e.Static() 和 middleware.Static() 默认不设置任何缓存头,响应里既没有 Cache-Control,也没有 ETag 或 Last-Modified。浏览器对每个静态资源都会发条件请求(304 Not Modified),哪怕文件根本没变——这拖慢首屏加载,也增加服务端 I/O 压力。
用 e.File() + 手动设头是最简可控方案
适合关键资源(如 /favicon.ico、/manifest.json、/robots.txt)或少量长期不变的文件:
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
e.File("/logo.svg", "assets/logo.svg")- 在对应 handler 里加头:
c.Response().Header().Set("Cache-Control", "public, max-age=31536000, immutable") - 注意:必须在
return前设置,且不能被后续中间件覆盖
批量静态资源需自定义中间件注入缓存头
若坚持用 e.Use(middleware.Static(...)) 服务整个 /static/ 目录,必须挂载自定义中间件,在响应发出前补上头:
- 只对匹配路径前缀(如
/static/、/assets/)生效,避免污染 API 或 404 响应 - 跳过
Content-Type: text/html(HTML 通常要协商缓存,而非强缓存) - 开发时建议用
if !e.Debug { ... }包裹,防止热更新失效 - 示例逻辑:
func cacheStaticMiddleware(prefix string, maxAge int) echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { p := c.Request().URL.Path if strings.HasPrefix(p, prefix) && c.Response().Status() == 200 { c.Response().Header().Set("Cache-Control", fmt.Sprintf("public, max-age=%d", maxAge)) } return next(c) } } }
别让 404 被缓存,也别给 HTML 加 immutable
缓存策略不是越长越好:
- 对
/static/js/app.js加immutable没问题,前提是文件名含哈希(如app.a1b2c3.js) - 但
/index.html必须用短缓存(max-age=60)或协商缓存(ETag),否则 HTML 更新后用户看不到新内容 - 如果中间件没判断状态码,
404响应也可能被缓存成public, max-age=31536000,导致错误长期滞留
e.File() 显式设头,HTML 单独处理协商缓存。










