游览器缓存问题

游览器缓存问题:

首先,一个返回200的请求可以来自游览器缓存,也可以来自服务器,具体是哪个,对于Chrome来说,要看network里的Size页面,是否有“from cache”说明.
同样的,对于一个Request Headers 中有 Cache-Control: no-cache 字段的请求,也不能判断它来自缓存还是服务器。这个字段出现在Request Headers的意义如下:

Cache-Control: no-cache is generally used in a request header (sent from web browser to server) to force validation of the resource in the intermediate proxies. If the client doesn't send this request to the server, intermediate proxies will return a copy of the content if it is fresh (has not expired according to Expire or max-age fields). Cache-Control directs these proxies to revalidate the copy even if it is fresh.

就是为了确保本次请求能得到服务器上的最新资源(注意,即使从服务器得到了304返回,也表明已经得到了服务器的最新资源)。
如果一个带有Cache-Control: no-cache的请求被缓存了,当它被从缓存读出后,仍然带有相应的Cache-Control: no-cache 字段,这时,已经不能说明这个请求是服务器上的最新资源了,还是要看游览器有没有注明这个请求是 “from cache”的。

即使是“from cache”也有2种效果:一种是200的“from cache”,这种就是直接从游览器的缓存中读取的,不能保证和服务器上的数据同步;第二种是304的“from cache”,这种是先发送了网络请求,从服务器得到了确认,再从本地缓存读取内容,可以保证数据和服务器上的数据同步。

image

从截图可以看出,from cache的请求用时都很短,只需要几毫秒;而从网络下载的,起码要几十毫秒。

关于Cache-Control: private

Indicates that all or part of the response message is intended for a single user and MUST NOT be cached by a shared cache, such as a proxy server.

其实,如果一个response的header中存在Cache-Control: private,就表明这个请求希望游览器使用缓存机制。

下面这个文章介绍了游览器的cache原理
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching

下面的文章解释了点击back按钮,游览器会从缓存读取内容,以及no-cache,no-store的作用:
https://stackoverflow.com/questions/29075375/cache-control-max-age-0-no-cache-but-browser-bypasses-server-query-and-hits

在ASP.Net中使用下面的代码

context.Response.Headers.Add("Cache-Control", new string[] { "no-cache" });

设置header的方法无法改变cache-control的值,总会被框架复写,所以需要下面这段代码

protected void Application_BeginRequest()
{
    Context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
}

对于采用了no-cache 设置的请求,游览器的前进和后退按钮还是会从cache中读取,因为前进和后退是游览器history功能的一部分,history的目的就是把用户上次看到的东西还原给用户。
但是,如果新建游览页(重不重启游览器都一样),再访问同样的网页,private 和 no-cache的请求产生的效果就不同了,no-cache 的请求会向服务器发送请求 而 private的请求 却直接被从cache中读出(chorme 和 IE相同)。参见下面2附图:

1.private

image

2.no-cache

image

在地址栏点击回车,不同的游览器表现不同。对于chrome 68.0.3440.84,一个private的请求也会向服务器校验,但是IE 11.165.17134.0不会,直接从cache中读取。其实这样的话,对于IE 11.165.17134.0 游览器,private就是一个十分不好的设置了,用户在游览器地址栏中重复回车,数据都无法刷新,只能通过刷新按钮才能刷新出新数据,十分不友好。所以如果程序是主要对IE 11.165.17134.0用户使用的,最好不用private,应该用 no-cache。no-cache 只是多了304的校验过程,对客户端来说,并不会浪费许多流量,一个304的返回往往不到1KB,但是多余的请求,会对服务器造成压力,这样就要根据具体的情况作出取舍了。

通过测试,还发现在IE 11.0.9600 上,在地址栏点击回车的效果和上面的chrome的效果一样,会像服务器发出请求。所以,如果确实希望某个请求被游览器cache,就应该使用 max-age = xxxx 这种属性,IE就会把它缓存。

遇到缓存问题,最好要到客户的客户端版本号,争取在相同环境下测试,通过更改服务器返回的response header中的cache-control字段,调整出客户需要的效果。


用chrome测试时,通过ctrl+F5刷新,request header中的cache-control是no-cache,通过F5或在地址栏敲入回车,header中的cache-control是max-age = 0。对于同一个游览器,发出的所有普通request(不是ajax),都有这个现象,它是跟游览器的实现逻辑有关的。

下面这个链接说明了 max-age = 0 和no-cache的区别
https://stackoverflow.com/questions/1046966/whats-the-difference-between-cache-control-max-age-0-and-no-cache


另外,目前就观察来看,游览器不缓存由Ajax发出的请求(就是使用XMLHttpRequest对象),只缓存剩下的普通请求。

IE游览器的调试状态的Network标签中有个按钮,叫做“Always refresh from server”,点击后,所有请求完全忽略本地缓存,调试的时候记得关闭。

posted @ 2018-10-11 10:13  幻化成疯  阅读(286)  评论(0编辑  收藏  举报