Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
yijingping opened this issue Apr 24, 2018 · 29 comments

Comments

@yijingping
Copy link

我的域名是 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 被缓存的问题?

@ant-design-bot
Copy link

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
Copy link
Collaborator

ctrl+shifit+r

@yijingping
Copy link
Author

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

@chenshuai2144
Copy link
Collaborator

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

@yijingping
Copy link
Author

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

@chenshuai2144
Copy link
Collaborator

试试这个

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

@yijingping
Copy link
Author

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

@chenshuai2144
Copy link
Collaborator

@sorrycc

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

@yijingping
Copy link
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
Copy link

yjy8749 commented Apr 27, 2018

应该是因为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
Copy link

neewbee commented Apr 30, 2018

我猜测一下:

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

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

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

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

@yijingping
Copy link
Author

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

@yijingping
Copy link
Author

@wangshuai0 我这是好的

@wangshuai0
Copy link

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

@kerwin-ly
Copy link

@yijingping nice!!!解决了困扰我好久的问题

@kennylbj
Copy link
Contributor

try this facebook/create-react-app#1910

@ghost
Copy link

ghost commented Feb 26, 2019

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

请问具体代码是怎么样的?我是vue开发,也是版本迭代,基本每周一次,每次都是缓存问题,心累,求解决办法。

@iiijarvis
Copy link

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

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

@ShawshankLin
Copy link

应该是因为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
Copy link

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

@qqwrv123
Copy link

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

@shanelau
Copy link

shanelau commented Jun 21, 2019

用下面的代码配置 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
Copy link

tiyunchen commented Jul 1, 2019

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

@mike96265
Copy link

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

@NMZD
Copy link

NMZD commented Dec 3, 2019

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

@Pengjee
Copy link

Pengjee commented May 8, 2020

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

@chwan97
Copy link

chwan97 commented Aug 14, 2021

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

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

@yll521
Copy link

yll521 commented Feb 7, 2022

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

@wmasfoe
Copy link

wmasfoe commented Apr 20, 2023

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

你小子

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests