怎么解决页面缓存
浏览器缓存分为:强缓存和协商缓存。
1、 强缓存 :浏览器加载资源时,第一步先判断它是否是强缓存,如果是,浏览器将直接从自己的缓存中读取, 不会 向服务器 发送请求 。
Expires字段 :1、浏览器第一次向服务器请求,服务器返回资源并在response header加上 Expires 字段,是客户端缓存有效期,是绝对时间。2、浏览器接收资源,把资源和相应头缓存起来。3、待到再次请求这个资源时,先在缓存中找,找到了看Expires字段,判断是否过期。若没过期直接从缓存加载。若过期了,再向服务器请求。
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: 如果页面过期敏野,则去服务器进行获取。
2、 协商缓存 :当浏览器判断不是强缓存,就会发向服务器 发请求 ,判断是否是协商缓存。如果是,服务器会返回304Not Modified,浏览器从缓存中加载。那什么又是协商缓存呢?
Last-Modified和If-Modified-Since字段 :1、浏览器第一次向服务器发请求,服务器返回资源并在response header加上 Last-Modified 字段,表示资源最后修改的时间。2、浏览器再次请求这个资源时,请求头会加上 If-Modified-Since 字段。若这两个字段一样,说明资源没有修改过,返回304Not Modified,浏览器从缓存中获取资源。若这两个字段不一样,说明资源修改过,服务器正常返回资源。
ETag、If-None-Match :1、浏览器第一次向服务器请求,服务器返回资源并在response header上加 ETag 字段。表示资源本身,资源有变化,则该字段有变化。2、浏览器再次向服务器请求这个资源时,请求头携带 If-None-Match 字段。若这两个字段相同,则代表资源没有变化,服务器返回304Not Modified,浏览器从缓存中加载。若两个字段不同,证明资源有变动,服务器正常返回资源。
Cache-Control与Expires的作用一致,都是指明当前资源的有效期,控制浏览汪拿颤器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。只不过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(实体标识)呢?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》,这里不再深入。
(一)静态资源缓存解决方法
现在的项目构建工具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 配置不缓存(单页应用)
当然并不是所有请求都能被缓存,无法被浏览器缓存的请求如下:
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的请求无法被缓存
广告 您可能关注的内容 |