怎么解决页面缓存

一、我们先来认识一下浏览器缓存

浏览器缓存分为:强缓存和协商缓存。
1、强缓存:浏览器加载资源时,第一步先判断它是否是强缓存,如果是,浏览器将直接从自己的缓存中读取,不会向服务器发送请求
Expires字段:1、浏览器第一次向服务器请求,服务器返回资源并在response header加上Expires字段,是客户端缓存有效期,是绝对时间。2、浏览器接收资源,把资源和相应头缓存起来。3、待到再次请求这个资源时,先在缓存中找,找到了看Expires字段,判断是否过期。若没过期直接从缓存加载。若过期了,再向服务器请求。

  • 但是绝对时间有时会有偏差,所以引出了Cache-Control。

Cache-Control字段:1、浏览器第一次向服务器请求,服务器返回资源并在response header加上Cache-Control字段,也是缓存的有效期,但是是相对时间,比如:Cache-Control:max-age=56700000。2、浏览器接收资源,把资源和相应头缓存下来。3、待到浏览器再次请求这个资源时,先在缓存找,根据第一次的请求时间和Cache-Control相对时间算出过期时间。若没过期,直接从缓存加载。若过期了,再向服务器请求。


简单介绍下Cache-Control的属性设置。
1)max-age: 设置缓存的最大的有效时间,单位为秒(s)。max-age会覆盖掉Expires
2) s-maxage: 只用于共享缓存,比如CDN缓存(s -> share)。与max-age 的区别是:max-age用于普通缓存,
而s-maxage用于代理缓存。如果存在s-maxage,则会覆盖max-age 和 Expires.
3) public:响应会被缓存,并且在多用户间共享。默认是public。
4) private: 响应只作为私有的缓存,不能在用户间共享。如果要求HTTP认证,响应会自动设置为private。
5)no-cache: 指定不缓存响应,表明资源不进行缓存。但是设置了no-cache之后并不代表浏览器不缓存,而是在缓存前要向服务器确认资源是否被更改。因此有的时候只设置no-cache防止缓存还是不够保险,还可以加上private指令,将过期时间设为过去的时间。
6)no-store: 绝对禁止缓存。
7)must-revalidate: 如果页面过期,则去服务器进行获取。

  • Cache-Control弥补了Expires的不足,更安全有效。

2、协商缓存:当浏览器判断不是强缓存,就会发向服务器发请求,判断是否是协商缓存。如果是,服务器会返回304Not Modified,浏览器从缓存中加载。那什么又是协商缓存呢?

Last-Modified和If-Modified-Since字段:1、浏览器第一次向服务器发请求,服务器返回资源并在response header加上Last-Modified字段,表示资源最后修改的时间。2、浏览器再次请求这个资源时,请求头会加上If-Modified-Since字段。若这两个字段一样,说明资源没有修改过,返回304Not Modified,浏览器从缓存中获取资源。若这两个字段不一样,说明资源修改过,服务器正常返回资源。

  • 但有时候服务器上资源有变化,单最后修改时间没更新,则引出下面两个字段。

如果资源修改非常频繁,在秒以下的时间内进行修改,而Last-modified只能精确到秒
某些服务器不能精确得到资源的最后修改时间,这样就无法通过最后修改时间判断资源是否更新
一些资源的最后修改时间改变了,但是内容没改变,使用ETag就认为资源还是没有修改的

ETag、If-None-Match:1、浏览器第一次向服务器请求,服务器返回资源并在response header上加ETag字段。表示资源本身,资源有变化,则该字段有变化。2、浏览器再次向服务器请求这个资源时,请求头携带If-None-Match字段。若这两个字段相同,则代表资源没有变化,服务器返回304Not Modified,浏览器从缓存中加载。若两个字段不同,证明资源有变动,服务器正常返回资源。

怎么解决页面缓存_第1张图片
image.png

强缓存:Cache-Control与Expires

Cache-Control与Expires的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。只不过Cache-Control的选择更多,设置更细致,如果同时设置的话,其优先级高于Expires。

协商缓存:Last-Modified/ETag与Cache-Control/Expires

配置Last-Modified/ETag的情况下,浏览器再次访问统一URI的资源,还是会发送请求到服务器询问文件是否已经修改,如果没有,服务器会只发送一个304回给浏览器,告诉浏览器直接从自己本地的缓存取数据;如果修改过那就整个数据重新发给浏览器;
  Cache-Control/Expires则不同,如果检测到本地的缓存还是有效的时间范围内,浏览器直接使用本地副本,不会发送任何请求。两者一起使用时,Cache-Control/Expires的优先级要高于Last-Modified/ETag。即当本地副本根据Cache-Control/Expires发现还在有效期内时,则不会再次发送请求去服务器询问修改时间(Last-Modified)或实体标识(Etag)了。

一般情况下,使用Cache-Control/Expires会配合Last-Modified/ETag一起使用,因为即使服务器设置缓存时间, 当用户点击“刷新”按钮时,浏览器会忽略缓存继续向服务器发送请求,这时Last-Modified/ETag将能够很好利用304,从而减少响应开销。

Last-Modified与ETag的关系(Etag:资源的内容标识)

如果两者同时存在,If-None-Match(Etag)优先,忽略If-Modified-Since(Last-Modified)

你可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag(实体标识)呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:
A.Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的新鲜度
B.如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存
C.有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形
Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。Etag的服务器生成规则和强弱Etag的相关内容可以参考,《互动百科-Etag》和《HTTP Header definition》,这里不再深入。

注意:Last-Modified/If-Modified-Since要配合Cache-Control使用,Etag/If-None-Match也要配合Cache-Control使用

二、页面缓存分为两部分,其一是HTML缓存,其二是页面内js,css等静态资源的缓存。

(一)静态资源缓存解决方法
现在的项目构建工具webpack,gulp 或者是vue-cli都可以在打包文件时为文件后缀自动加上版本号,有了随机版本号这样只要文件有所改动,浏览器在请求文件时就会因为版本号不一样,重新向服务器请求,而不去使用浏览器所缓存的资源。
(二)HTML缓存
HTML缓存,HTMl缓存不解决,对于单页面应用来说,如果不解决HTML缓存,只解决静态资源js,css缓存是不可以的,因为只要index.html页面内容不变,入口页面上请求的js,css文件版本号是不会改变的,所以应该在解决了HTML缓存的基础上来解决js,css缓存问题。
解决HTML缓存的方法:具体可以参考: https://www.cnblogs.com/zhuzhenwei918/p/6028414.html

在页面顶部加如下标签:



但是,遗憾的告诉你,这还不是最终解决的方法,因为加上这些meta标签后,我自己在项目里发现,有时候起作用有时候不管用。
接下来要做的是 nginx 配置不缓存(单页应用)

location = /MicroNew/start.html {
etag off;
add_header Cache-Control "no-cache, no-store";
root /home/new_zhiliao/upload/zhiliao/;
}

三、用户行为与缓存

  • F5刷新

Expires/Cache-Control 无效(BR重置max-age=0)
Last-Modified/Etag 有效

  • Ctrl+F5刷新

Expires/Cache-Control 无效(重置Cache-Control=no-cache)
Last-Modified/Etag 无效(请求头丢弃该选项)

四、不能缓存的请求:

当然并不是所有请求都能被缓存,无法被浏览器缓存的请求如下:

1. HTTP信息头中包含Cache-Control:no-cache,pragma:no-cache(HTTP1.0),或Cache-Control:max-age=0等告诉浏览器不用缓存的请求

2. 需要根据Cookie,认证信息等决定输入内容的动态请求是不能被缓存的

3. 经过HTTPS安全加密的请求(有人也经过测试发现,ie其实在头部加入Cache-Control:max-age信息,firefox在头部加入Cache-Control:Public之后,能够对HTTPS的资源进行缓存,参考《HTTPS的七个误解》)

4. POST请求无法被缓存

5. HTTP响应头中不包含Last-Modified/Etag,也不包含Cache-Control/Expires的请求无法被缓存

你可能感兴趣的:(怎么解决页面缓存)