RuoYi Vue 管理后台页面的 Nginx 缓存问题

文章目录

    目前的 RuoYi Vue 管理后台的前端发布之后,浏览器还是会缓存上一次发布的页面,触发手动刷新一下浏览器才能看到最新版本的前端页面。 目前使用的是 nginx 部署的。

    修改前返回的 HTTP 头

    HTTP/1.1 200 OK 
    Server: nginx/1.30.4 
    Date: Wed, 21 Oct 2026 07:29:39 GMT 
    Content-Type: text/html 
    Content-Length: 52778 
    Last-Modified: Mon, 19 Oct 2026 04:00:22 GMT 
    Connection: keep-alive 
    ETag: "6ad595d6-ce2a" 
    Accept-Ranges: bytes 
    

    禁止页面缓存

    旧的 Nginx 配置:

    location / {
        root   /var/www/sunzhongwei.com/dist;
        try_files $uri $uri/ /index.html;
        index  index.html index.htm;
    }
    

    目前这个 location / 完全没有设置任何缓存头。nginx 对静态文件默认只下发 Last-Modified / ETag,浏览器会对 index.html 做”启发式缓存”(通常按 (当前时间 - Last-Modified) × 10% 来缓存),导致发版后浏览器仍然拿着旧的 index.html → 引用旧的 hash 资源名 → 页面不更新,必须手动刷新。

    Vue 构建产物(app.8f3a2c.js、chunk-vendors.xxx.css)文件名本身带内容 hash,内容一变文件名就变,所以这些静态资源可以放心地长缓存;真正需要”每次都拿最新”的只有一个入口文件 index.html。

    关键陷阱:SPA 的 try_files $uri $uri/ /index.html 回退时,浏览器请求的是根路径 /,匹配的是 location / 本身,URI 并不是 *.html,所以很多人写的 location ~* \.html$ { ... } 根本拦不到根路径回退。最稳妥的办法是按响应 Content-Type 来区分缓存策略。

    需要两处改动:

    ① map 必须写在 http 上下文(nginx.conf 主配置或 conf.d/ 下被 http { ... } include 的文件里,不能写在 server 块内):

    # http 上下文:按响应类型设置缓存策略
    map $sent_http_content_type $cache_control {
        default "public, max-age=31536000, immutable";   # 带 hash 的 js/css/img 等长缓存
        ~text/html "no-cache, no-store, must-revalidate"; # 入口 HTML 每次都重新校验
    }
    

    ② 在现有 server 的 location / 里加一行 add_header:

    location / {
        root   /var/www/sunzhongwei.com/dist;
        try_files $uri $uri/ /index.html;
        index  index.html index.htm;
    
        # 入口 HTML 不缓存(含 SPA 根路径回退),静态资源长缓存
        add_header Cache-Control $cache_control;
    }
    

    这样:
    - 访问 /(回退到 index.html,Content-Type 是 text/html)→ Cache-Control: no-cache, no-store, must-revalidate,浏览器每次都向服务端校验,拿到最新的 index.html;
    - 访问 /js/app.8f3a2c.js(Content-Type 是 application/javascript)→ Cache-Control: public, max-age=31536000, immutable,一年内直接命中本地缓存,无需重新下载。

    因为新发布后 index.html 一定是最新的,它引用的就是新 hash 资源名,刷新即生效。

    改完配置后 nginx -t && nginx -s reload

    修改后返回的 HTTP 头

    HTTP/1.1 200 OK
    Server: nginx/1.30.4
    Date: Wed, 21 Oct 2026 07:35:25 GMT
    Content-Type: text/html
    Content-Length: 52778
    Last-Modified: Mon, 19 Oct 2026 04:00:22 GMT
    Connection: keep-alive
    ETag: "6ad595d6-ce2a"
    Cache-Control: no-cache, no-store, must-revalidate
    Accept-Ranges: bytes
    

    果然 OK 了。