Skip to content

前端重定向,index.html文件被浏览器缓存,导致整个应用都是旧的 #1365

@yijingping

Description

@yijingping

我的域名是 example.com,
访问 http://example.com,在前端会默认路由到 http://example.com/dashbord/

这个时候,如果代码有更新。 我访问http://example.com/dashbord/ 可以获取到最新内容。
但是访问http://example.com,浏览器url变成http://example.com/dashbord/,但页面是上次缓存的。 HTTP response status是: 200 (from disk cache)

请问如何解决 重定向 index.html 被缓存的问题?

Activity

ant-design-bot

ant-design-bot commented on Apr 24, 2018

@ant-design-bot

Translation of this issue:


Front-end redirection, index.html file is cached by the browser, resulting in the entire application is old

My domain is example.com,
Visit http://example.com and the default route will be http://example.com/dashbord/

This time, if the code is updated. I can get the latest content by visiting http://example.com/dashbord/.
However, when visiting http://example.com, the browser url becomes http://example.com/dashbord/, but the page was last cached. HTTP response status is: 200 (from disk cache)

How to solve the problem of redirecting index.html cached?

chenshuai2144

chenshuai2144 commented on Apr 25, 2018

@chenshuai2144
Collaborator

ctrl+shifit+r

yijingping

yijingping commented on Apr 25, 2018

@yijingping
Author

@chenshuai2144 我知道自己如何去清缓存。 但是我不能让用户每次访问我的网站的时候,都强刷一次

chenshuai2144

chenshuai2144 commented on Apr 25, 2018

@chenshuai2144
Collaborator

线上版本为什么会需要经常改动!
每次构建出来的 js hash 都不一样的

yijingping

yijingping commented on Apr 25, 2018

@yijingping
Author

@chenshuai2144 迭代开发,每隔几天都会上线新功能,当然会经常变动。 js hash 确实不一样, 但是html文件被缓存了,导致引用的旧的js css 文件。

chenshuai2144

chenshuai2144 commented on Apr 25, 2018

@chenshuai2144
Collaborator

试试这个

<HEAD>
<METAHTTP-EQUIV="Pragma"CONTENT="no-cache">
<METAHTTP-EQUIV="Cache-Control"CONTENT="no-cache">
<METAHTTP-EQUIV="Expires"CONTENT="0">
</HEAD>
yijingping

yijingping commented on Apr 25, 2018

@yijingping
Author

这个加过了,对于跳转的页面不生效。
http://example.com,在前端会默认路由到 http://example.com/dashbord/, 显示的是旧的版本。
但直接访问 http://example.com/dashbord/,显示的是新版本

chenshuai2144

chenshuai2144 commented on Apr 25, 2018

@chenshuai2144
Collaborator

@sorrycc

这个问题很奇怪, 你解决过吗?

yijingping

yijingping commented on Apr 26, 2018

@yijingping
Author

在HTTP协议中,只有后端返回 expires 或 Cache-Control:max-age=XXX, 前端才缓存。
但在浏览器中,默认会对 html css js 等静态文件、以及重定向进行缓存,如果在HEAD头中指定:

<HEAD>
<METAHTTP-EQUIV="Pragma"CONTENT="no-cache">
<METAHTTP-EQUIV="Cache-Control"CONTENT="no-cache">
<METAHTTP-EQUIV="Expires"CONTENT="0">
</HEAD>

浏览器不会缓存html,但是还是会对重定向缓存,并且这种方式并不规范,可能有的浏览器不支持。

我的最终解决方案是:
1) 对hash过的静态文件还是采用默认方式,客户端会缓存。
2)对html文件,返回时增加头:Cache-Control,必须每次来服务端校验,根据etag返回200或者304

对应的nginx配置如下:

upstream example-be {
    ip_hash;
    server unix:/run/example-be.sock;
}
server{
    listen   80; #监听端口
    server_name example.com

    # 后台api
    location ~ ^/api {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        include uwsgi_params;
        uwsgi_pass example-be;
    }

    # 前端静态文件
    location ~* \.(gif|jpg|jpeg|png|css|js|ico|eot|otf|fon|font|ttf|ttc|woff|woff2)$ {
        root /var/www/example-fe/dist/;
    }

    # 前端html文件
    location / {
        # disable cache html
        add_header Cache-Control 'no-cache, must-revalidate, proxy-revalidate, max-age=0';

        root /var/www/example-fe/dist/;
        index index.html index.htm;
        try_files $uri /index.html;
    }
}

由于浏览器缓存静态文件的时间不可控,我们可以在nginx上自己配置expires 1M(1个月)

    # 前端静态文件
    location ~* \.(gif|jpg|jpeg|png|css|js|ico|eot|otf|fon|font|ttf|ttc|woff|woff2)$ {
        root /var/www/example-fe/dist/;
        expires 1M;
        add_header Cache-Control "public";
    }
yjy8749

yjy8749 commented on Apr 27, 2018

@yjy8749

应该是因为index.html被浏览器缓存了, 虽然已经发布了新版本但是由于请求index.html是直接命中了浏览器缓存导致请求并未到达服务器,直接使用的缓存的index.html的内容,这也导致了 <script> 加载index.js时版本不正确.部分浏览器对于METAHTTP的支持也不同,所以设置了也不行.

<script type="text/javascript" src="/index.17b3674f.js"></script></body>

说个解决思路:
首先webpack打包时 在index.html中记录一个 预计的下次发布时间
index.html加载时检查是否超过该时间,如果超过了就通过 window.location 重新请求index.html
请求时需要带上日期以防止浏览器缓存 index.html?t=20180206,修改t的值可控制index.html超过时间后的缓存周期 如按日缓存,按小时缓存.

neewbee

neewbee commented on Apr 30, 2018

@neewbee

我猜测一下:

这个加过了,对于跳转的页面不生效。
http://example.com,在前端会默认路由到 http://example.com/dashbord/, 显示的是旧的版本。

浏览器缓存了这个域名的index.html文件

但直接访问 http://example.com/dashbord/,显示的是新版本

浏览器检查有没有缓存相应的html文件(没有,因为这是一个客户端路由),发出请求 ,nginx 接收到请求,发现不存在相关的html 文件,于是返回 index.html 文件(try_files),现在返回的index.html是你最新的文件。

yijingping

yijingping commented on May 2, 2018

@yijingping
Author

@neewbee 访问 http://example.com/dashbord/ 时,请求带有etag,服务端返回的是304。 所以客户端应该是有这个版本的html的

yijingping

yijingping commented on Aug 28, 2018

@yijingping
Author

@wangshuai0 我这是好的

wangshuai0

wangshuai0 commented on Aug 28, 2018

@wangshuai0

@yijingping 后面我又试了下,是好的,为了测试,我又把这个配置在nginx上去掉后发现点击链接跳转还是加载到了新的页面没有出现( 200 (from disk cache),不知道是什么原因。

3 remaining items

iiijarvis

iiijarvis commented on Mar 13, 2019

@iiijarvis

@yijingping 我测试发现设置 add_header Cache-Control 'no-store'; 才行。

add_header Cache-Control 'no-cache, must-revalidate, proxy-revalidate, max-age=0'; 仍会返回 304

ShawshankLin

ShawshankLin commented on May 7, 2019

@ShawshankLin

应该是因为index.html被浏览器缓存了, 虽然已经发布了新版本但是由于请求index.html是直接命中了浏览器缓存导致请求并未到达服务器,直接使用的缓存的index.html的内容,这也导致了 <script> 加载index.js时版本不正确.部分浏览器对于METAHTTP的支持也不同,所以设置了也不行.

<script type="text/javascript" src="/index.17b3674f.js"></script></body>

说个解决思路:
首先webpack打包时 在index.html中记录一个 预计的下次发布时间
index.html加载时检查是否超过该时间,如果超过了就通过 window.location 重新请求index.html
请求时需要带上日期以防止浏览器缓存 index.html?t=20180206,修改t的值可控制index.html超过时间后的缓存周期 如按日缓存,按小时缓存.

其实更好的解决办法是不是在更新的时候获取客户端的git版本,然后写在index.html,然后index.html每次去判断本地的缓存的git版本是否跟index.html的版本小,如果小就刷新

KaroseLiu

KaroseLiu commented on May 10, 2019

@KaroseLiu

@yijingping 我的nginx也是这样配置,但是还是不行,最终找到原因是因为,serviceWorker 帮我缓存了html文件,导致一直是旧的版本,我把 serviceWorker unregister了,世界又恢复正常了~

qqwrv123

qqwrv123 commented on Jun 21, 2019

@qqwrv123

没有使用nginx该怎么禁止html缓存

shanelau

shanelau commented on Jun 21, 2019

@shanelau

用下面的代码配置 nginx,完美解决 public 是不行的

  # 前端静态文件
    location ~* \.(gif|jpg|jpeg|png|css|js|ico|eot|otf|fon|font|ttf|ttc|woff|woff2)$ {
        root /var/www/example-fe/dist/;
        expires 1M;
        add_header Cache-Control "no-cache";
    }

no-cache 表示不缓存过期资源,缓存会向服务器进行有效处理确认之后处理资源,即 304

no-store 才是真正的不进行缓存。

public 表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存,即使是通常不可缓存的内容(例如,该响应没有max-age指令或Expires消息头)。

tiyunchen

tiyunchen commented on Jul 1, 2019

@tiyunchen

在部署完成的时候,我点击页面内某个路由他不是新开页面跳转,而是push的方式加载路由,但是新代码就不会更新,该怎么解决?

mike96265

mike96265 commented on Nov 19, 2019

@mike96265

如果nginx回复头设置缓存策略cache-control为no_cache,no_store,然后增加一个回复头 标志index.html sha512值,前端保存下来这个值,同时每次调用接口之后都检查这个值和本地保存的值,如果两个值不一样就重载index.html,不知道这样是否可行。因为考虑到实际上很多情况是因为后端接口不兼容,如果都是静态界面,只是显示旧的界面并不会有啥问题。

NMZD

NMZD commented on Dec 3, 2019

@NMZD

确实配上no-store才能不缓存,已测试,解决了很久的困扰,感谢分享

Pengjee

Pengjee commented on May 8, 2020

@Pengjee

那如果用户就是使用这个平台,然后这时候发布了一个功能,用户切换页面的时候就会导致页面资源文件丢失的情况

chwan97

chwan97 commented on Aug 14, 2021

@chwan97

那如果用户就是使用这个平台,然后这时候发布了一个功能,用户切换页面的时候就会导致页面资源文件丢失的情况

不下线就资源就不会显示丢失,主楼的问题就是自己的nginx配置有问题或者CDN配置有问题把HTML给缓存了

yll521

yll521 commented on Feb 7, 2022

@yll521

其实有一种暴力方式 每次发版重启服务最简单

wmasfoe

wmasfoe commented on Apr 20, 2023

@wmasfoe

其实有一种暴力方式 每次发版重启服务最简单

你小子

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @yijingping@shanelau@yjy8749@kennylbj@chenshuai2144

        Issue actions

          前端重定向,index.html文件被浏览器缓存,导致整个应用都是旧的 · Issue #1365 · ant-design/ant-design-pro