一、浏览器缓存
这一点主要解析浏览器缓存以及缓存机制的详细过程。
与缓存相关的状态码:
200 ok 从浏览器下载的最新资源
200 (from memory cache) 不进行http请求,直接从浏览器内存中读取的资源,页面关闭,则资源释放,一般一些脚本、图片、文字等会存在内存中
200 (from disk cache) 不进行http请求,直接从磁盘中读取的资源,页面关闭,资源仍然存在,除非清除缓存,一般一些非脚本文件会存在磁盘中,例如html、css文件
304 (not modified) 请求了服务器,但是由于服务器资源没有更新,所以仍使用内存中的资源
缓存相关的http header介绍:
http header 介绍
cache-control response header or request header;指定缓存机制,优先级最高
expires response header or request header;指定缓存的过期时间(现在浏览器一般设置cache-control,设置expires是为了兼容http1.0)
last-modified response header;资源的最后修改时间
etag response header;资源的唯一标识符
if-modified-since request header;缓存的服务器资源的最后修改时间
if-none-match request header;缓存的服务器资源的唯一标识
1.1强缓存:
不会进行http请求,读取的是内存中的资源,直到缓存失效
涉及到的状态码:
200(from memory cache)
200(from disk cache)
涉及到的http header:
cache-control
expires
当浏览器对某个资源的请求命中了强缓存时,返回的http状态码为200,在chrome开发者工具中的network中的size会显示from cache
强缓存时利用Expires或者Cache-Control这两个http header实现的,都用来表示资源在客户端缓存的有效期
Expires是http1.0提出的一个header,描述的是一个绝对时间,由服务器返回,用GMT格式的字符串表示,如Exprires:Thu,31 Dec 2037 23:55:55 GMT
缓存过程:
1、浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在response的header加上Expires的header
2、浏览器在接收到这个资源后,会把这个资源连同所有的response header一起缓存下来,所以缓存命中的请求返回的header并不是来自服务器,而是来自之前缓存的header
3、浏览器再请求这个资源时,先从缓存中寻找,找到这个资源后,拿出Expires跟当前的请求时间比较,如果请求时间在Expires指定的时间之前,就能命中缓存,否则就不行。
4、如果缓存没有命中,浏览器直接从服务器加载资源时,Expires Header在重新加载的时候会被更新
Expires是服务器返回的一个绝对时间,在服务器时间与客户端时间相差较大时,缓存管理容易出现问题,比如随意修改下客户端时间,就能影响缓存命中的结果,所以在http1.1的时候,提出了一个新的header,也就是Cache-Control,这是一个相对时间,在进行缓存命中的时候,都是利用客户端时间进行判断,因此更有效安全一些,在配置缓存的时候,以秒为单位,用数值表示:如:Cache-Control:max-age=315360000,它的缓存过程是:
1、浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在response的header加上Cache-Control的header
2、浏览器在接收到这个资源的时候,会把这个资源连同所有response header一起缓存下来
3、浏览器再次请求这个资源的时候,先从缓存中寻找,找到这个资源之后,再拿这个过期时间跟当前的请求时间比较,如果请求时间在过期时间之前,就能命中缓存,否则就不行。
4、如果缓存没有命中,浏览器直接从服务器加载资源时,Cache-Control在重新加载的时候会被更新
cache-control
优先级最高,所有的缓存机制看到 cache-control 都要服从它;在请求头和响应头中都可以设置;cache-control有多种设置,设置如下:
cache-control 描述
no-store 请求和响应都不缓存(禁用)
no-cache 协商缓存,相当于cache-control:max-age=0(每次取之前先跟服务器沟通比较)
max-age 指定缓存内容将在xxx秒后失效
public 所有内容都将被缓存(客户端和代理服务器都可缓存)
private 所有内容只有客户端可以缓存,Cache-Control的默认取值
注意:这个header可以只用一个,也可以同时用两个,同时存在时,Cache-Control优先级高于Expires
1.2 强缓存的管理
两种方式来设置是否启用强缓存:
1、通过代码的方式,在web服务器返回的响应中添加Expires和Cache-Control Header
2、通过配置web服务器的方式,让web服务器在响应资源的时候统一添加Expires和Cache-Control Header
1.3 强缓存的应用
强缓存是前端性能优化最有力的工具,对于有大量静态资源的网页,一定要利用强缓存,提高响应速度,通常是为这些静态资源全部配置一个超时时间超长的Expires或Cache-Control,这样用户只会在第一次访问网站时加载静态资源,其他时间只要缓存没有失效并且用户没有强制刷新的条件下都会从缓存中加载。
然而这种缓存配置方式会带来一个问题,就是当资源更新时,客户端由于有缓存不会向服务器请求最新的资源,这个问题已有解决方案:
通过更新页面中引用的资源路径,让浏览器主动放弃缓存,加载新资源。
但要实现有更新的文件才需要浏览器重新加载,因此必须让url的修改与文件内容相关联,利用数据摘要算法对文件求摘要信息,摘要信息与文件内容一一对应,这一点许多前端构建工具都做到了,如webpack
1.4 浏览器默认缓存使开发环境下常因为资源没有及时更新而看不到效果
解决方法:
1、ctrl+F5
2、浏览器隐私模式开发
3、chrome开发者工具里将Disable cache选项打勾,阻止缓存
4、在开发阶段,给资源加上一个动态的参数,由于每次资源的修改都要更新引用的位置,同时修改参数的值,所以操作起来不是很方便,除非是在动态页面比如jsp里开发就可以用服务器变量来解决,或者用前端构建工具来处理这个参数修改的问题。
5、如果资源引用的页面被嵌入到了一个iframe里面,可以在iframe的区域右键重新加载该页面
6、如果缓存问题出现在ajax请求中,最有效的解决办法就是ajax的请求地址追加随机数
7、动态设置iframe的src时,有可能因为缓存问题导致看不到最新效果,在src后面添加随机数即可
8、通过前端开发工具grunt gulp等的插件来启动一个静态服务器,则在这个服务器下所有资源返回的response header中,Cache-Control始终被设置为不缓存
1.5 发布问题
发布问题:若页面和它引用的资源路径同时更新了,不管是先部署页面还是先部署资源都会带来各种问题,这是由于资源是覆盖式发布的,即用待发布资源覆盖已发布资源。
解决办法就是实现非覆盖式发布:把有修改的资源文件作为一个新的文件发布,不对已有的资源文件进行覆盖,这样用户还可以请求旧的资源文件,不至于发生页面错乱的问题,这样先部署静态资源,再覆盖式部署页面,等到用户访问新页面的时候,新的资源文件也已发布,就可以正确请求,即可解决问题。
2.1 协商缓存
涉及到的状态码:
304 not modified
200 ok
涉及到的请求头
etag / ig-none-match
last-modified / if-modified-since
如果命中协商缓存,请求响应返回的http状态为304以及一个Not Modified字符串,协商缓存利用的是【Last-Modified、If-Modified-Since】、【ETag、If-None-Match】这两对header来管理的。
【Last-Modified、If-Modified-Since】:
1、浏览器第一次跟服务器请求一个资源,服务器在返回这个资源时,在response的header加上Last-Modified的header,表示这个资源在服务器上的最后修改时间
2、浏览器再次向服务器请求这个资源时,在request的header加上If-Modified-Since的header,这个header的值就是上一次请求时返回的Last-Modified的值
3、服务器再次收到资源请求时,根据浏览器传过来If-Modified-Since和资源在服务器上的最后修改时间判断资源是否有变化,如果没有变化则返回304 Not Modified,但是不会返回资源内容,如果有变化就返回资源内容,当服务器返回304 Not Modified的响应时,response header中不会再添加Last-Modified的header,因为资源没有变化,Last-Modified的值也不变
4、浏览器收到304的响应后,就会从缓存中加载资源
5、如果协商缓存没有命中,浏览器直接从服务器加载资源时,Last-Modofied header在重新加载的时候会被更新,下次请求时,If-Modified-Since会采用上一次返回的Last-Modified的值
这一对header都是根据服务器时间返回的,有时候会有服务器资源有变化,但最后修改时间却没有变化的情况,因此有了
【Etag、If-None-Match】:
1、浏览器第一次向服务器请求一个资源,服务器在返回这个资源的同时,在response的header加上ETag的header,这个header是服务器根据当前请求的资源生成的一个唯一标识,是一个字符串,只要资源内容发生改变,这个字符串也会改变,跟时间没有关系
2、浏览器再次请求这个资源的时候,在request的header上加上If-None-Match的header。这个header的值是上一次请求返回的ETag的值
3、服务器再次收到资源请求时,根据客户端传过来的If-None-Match和重新生成的该资源的新的ETag做比较,相同则返回304 Not Modified,不会返回资源内容,如果不同则返回资源内容,但这里即使资源没有发生变化,也会返回ETag,因为这个ETag重新生成过,即使没有ETag没有变化
4、浏览器收到304响应后,就从缓存中加载资源
etag两种类型:
强etag:
不论实体发生多么细微的变化都会改变其值
强ETag表示形式:"22FAA065-2664-4197-9C5E-C92EA03D0A16"。
弱etag:
弱 ETag 值只用于提示资源是否相同。只有资源发生了根本改变产 生差异时才会改变 ETag 。这时,会在字段值最开始处附加 W/。
弱ETag表现形式:W/"22FAA065-2664-4197-9C5E-C92EA03D0A16"。
注意:当etag和last-modified同时存在时则以etag为准
2.2 协商缓存的管理文章来源:https://www.toymoban.com/news/detail-854888.html
一般服务器上的【Last-Modified、If-Modified-Since】和【Etag、If-None-Match】会同时启用,协商缓存需要配合强缓存使用文章来源地址https://www.toymoban.com/news/detail-854888.html
到了这里,关于浏览器缓存(强缓存、协商缓存)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!