浏览器缓存做为性能优化的重要一环,对于前端而言,重要性不言而喻。之前老是只知其一;不知其二的,因此此次好好整理总结了一下。
首先咱们来整体感知一下它的匹配流程,以下:css
强缓存:不会向服务器发送请求,直接从缓存中读取资源。前端
强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程,强制缓存的状况主要有三种(暂不分析协商缓存过程),以下:nginx
那么强制缓存的缓存规则是什么?
当浏览器向服务器发起请求时,服务器会将缓存规则放入HTTP响应报文的HTTP头中和请求结果一块儿返回给浏览器,控制强制缓存的字段分别是Expires
和Cache-Control
,其中Cache-Control
优先级比Expires
高。git
缓存过时时间,用来指定资源到期的时间,是服务器端的具体的时间点。也就是说,Expires=max-age + 请求时间
,须要和Last-modified
结合使用。Expires
是Web服务器响应消息头字段,在响应http请求时告诉浏览器在过时时间前浏览器能够直接从浏览器缓存取数据,而无需再次请求。github
Expires 是 HTTP/1 的产物,受限于本地时间,若是修改了本地时间,可能会形成缓存失效。
在HTTP/1.1中,Cache-Control是最重要的规则,主要用于控制网页缓存,主要取值为:浏览器
Cache-Control
的默认取值须要注意的是,no-cache
这个名字有一点误导。设置了no-cache
以后,并非说浏览器就再也不缓存数据,只是浏览器在使用缓存数据时,须要先确认一下数据是否还跟服务器保持一致,也就是协商缓存。而no-store
才表示不会被缓存,即不使用强制缓存,也不使用协商缓存
强缓存须要服务端设置expires
和cache-control
。nginx
代码参考,设置了一年的缓存时间:缓存
location ~ .*\.(ico|svg|ttf|eot|woff)(.*) { proxy_cache pnc; proxy_cache_valid 200 304 1y; proxy_cache_valid any 1m; proxy_cache_lock on; proxy_cache_lock_timeout 5s; proxy_cache_use_stale updating error timeout invalid_header http_500 http_502; expires 1y; }
浏览器的缓存存放在哪里,如何在浏览器中判断强制缓存是否生效?这就是下面咱们要讲到的from disk cache
和from memory cache
。性能优化
细心地同窗在开发的时候应该注意到了Chrome的网络请求的Size会出现三种状况from disk cache(磁盘缓存)
、from memory cache(内存缓存)
、以及资源大小数值。服务器
状态 | 类型 | 说明 |
---|---|---|
200 | form memory cache | 不请求网络资源,资源在内存当中,通常脚本、字体、图片会存在内存当中 |
200 | form disk ceche | 不请求网络资源,在磁盘当中,通常非脚本会存在内存当中,如css等 |
200 | 资源大小数值 | 从服务器下载最新资源 |
304 | 报文大小 | 请求服务端发现资源没有更新,使用本地资源 |
浏览器读取缓存的顺序为memory –> disk。
以访问https://github.com/xiangxingchen/blog
为例
咱们第一次访问时https://github.com/xiangxingchen/blog
关闭标签页,再此打开https://github.com/xiangxingchen/blog
时
F5刷新时网络
简单的对比一下
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要有如下两种状况:
response header
中返回请求的资源上次更新时间,就是last-modified
,浏览器会缓存下这个时间。request header
中带上if-modified-since
:[保存的last-modified的值]
。根据浏览器发送的修改时间和服务端的修改时间进行比对,一致的话表明资源没有改变,服务端返回正文为空的响应,让浏览器中缓存中读取资源,这就大大减少了请求的消耗。因为last-modified依赖的是保存的绝对时间,仍是会出现偏差的状况:
etag
是http
协议提供的若干机制中的一种Web
缓存验证机制,而且容许客户端进行缓存协商。生成etag经常使用的方法包括对资源内容使用抗碰撞散列函数,使用最近修改的时间戳的哈希值,甚至只是一个版本号。 和last-modified
同样.
etag
的值,而后再下一次请求在request header
中带上if-none-match
:[保存的etag的值]
。etag
的值和服务端从新生成的etag
的值进行比对,若是一致表明资源没有改变,服务端返回正文为空的响应,告诉浏览器从缓存中读取资源。etag可以解决last-modified的一些缺点,可是etag每次服务端生成都须要进行读写操做,而last-modified只须要读取操做,从这方面来看,etag的消耗是更大的。
两者对比
Etag
要优于Last-Modified
。Etag
。Etag
要逊于Last-Modified
disk cache
中是否有匹配。若有则使用;如没有则发送网络请求。memory cache
是可用的,会被优先使用(若是匹配的话)。其次才是 disk cache
。Cache-control:no-cache
(为了兼容,还带了 Pragma:no-cache
),服务器直接返回 200 和最新内容。若是有错误或者不严谨的地方,请务必给予指正,十分感谢。若是喜欢或者有所启发,欢迎 star对做者也是一种鼓励。