在前端的性能优化中,浏览器缓存是很重要的一环。比如在页面前进或者后退,发现丝毫不卡顿很流畅,就是缓存机制的力量。
浏览器缓存Brower Caching是浏览器对之前请求过的文件进行缓存,以便再次访问的时候提高页面展示的速度。比如当我们第一次访问CSDN网站的时候,PC会把从网站上的图片和数据下载到电脑上。当再次访问CSDN网站的时候,网站直接从PC加载,这就是缓存。
(1)浏览器缓存是将文件保存在客户端,减少重复请求浪费网络带宽,只产生很小的网络消耗。
ps:打开本地资源也会产生网络消耗
(2)缓解服务器的压力,不用重复请求数据
(3)提升前端性能,提高访问速度,提供更好的用户体验
①数据库缓存
将查询后的数据放在内存中进行缓存,下次再查询,直接从内存缓存中获取,提高响应速度
②CDN缓存
发送web请求,cdn计算出路径短且快的路。管理员部署,把经常访问的放入cnd加快响应
③代理服务器缓存
与浏览器缓存机制类似,但代理服务器面向更广大的群体,规模更大。不只是为一个用户服务,而是为一群用户服务。
④浏览器缓存
每个浏览器都实现HTTP缓存。浏览器使用HTTP协议与服务器交互,根据与服务器约定的规则进行缓存工作
浏览器缓存的位置一般为四类:Server Worker、Memory Cache、Disk Cache、Push Cache
浏览器缓存过程:强缓存、协商缓存
第一次请求
再次请求
Server Worker 是运行在浏览器的独立线程,一般用来缓存。Server Worker 涉及请求拦截,so传输协议是HTTPS来保障安全。
Server Worker 是“外建”的缓存机制,可以自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的,这是与其他内建缓存机制的区别。
内存中的缓存,主要包含的是当前中页面中已经抓取到的资源,例如页面上已经下载的样式、脚本、图片等,占据该进程一定的内存资源,但是缓存持续性很短,会随着进程的释放而释放。一旦我们关闭 Tab 页面,内存中的缓存也就被释放了。
内存缓存特点:①读取速度快 ②时效性:页面关闭进程的内存清空释放
硬盘中的缓存。在所有浏览器缓存中,Disk Cache 覆盖面基本是最大的,绝大部分的缓存都来自 Disk Cache。为什么呢?cuz根据 HTTP Herder 中的字段判断哪些资源需要缓存,哪些资源可以不请求直接使用,哪些资源已经过期需要重新请求。在跨站点的情况下,相同地址的资源一旦被硬盘缓存下来,就不会再次去请求数据。
硬盘缓存比内存缓存读取速度慢,读取需要对硬盘进行I/O操作,会导致重新解析缓存内容,造成读取路的复杂。
Memory Cache 和 Disk Cache的相同和不同比较
Memory Cache | Disk Cache | |
---|---|---|
相同点 | 只能存储一些派生类资源文件 | 只能存储一些派生类资源文件 |
不同点 | 退出Tag进程时数据会被清除 | 退出Tag进程时数据不会被清除 |
存储资源 | 一般脚本、图片、字体 | 一般非脚本css等 |
CSS文件加载一次就可以渲染,不会频繁的读取,存储在Disk Cache;js脚本可能会随时会被执行,存储在Memory Cache,若存储在硬盘中,会因为I/O开销大导致浏览器失去响应。
三级缓存原理
①先去内存查找,找到直接加载
②内存找不到,硬盘中找,找到直接加载
③硬盘找不到进行网络请求
④请求获取的资源缓存到硬盘和内存
prefetch cache 预取缓存
html代码的link标签带有prefetch,prefetch是预加载的一种方式,被标记为prefetch的资源会在浏览器空闲的时间加载
推送缓存,是HTTP/2的内容,并没有严格执行HTTP头部的缓存指令。在Server Worker、Memory Cache、Disk Cache都没有命中的时候,它会被使用。在Session中存在,Session结束就会被释放,缓存时间短暂。
浏览器缓存机制就是HTTP缓存机制,这个机制HTTP报文的缓存标识进行的。
请求行—HTTP行(通用信息头、请求头、实体头)—请求报文主体(post才有)
状态行 – HTTP头(通用信息头,响应头,实体头) – 响应报文主体
200 form memory cache | 200 from disk cache |
---|---|
不访问服务器!直接从内存中获取。浏览器关闭,资源将被释放,数据将不存在。下次打开页面不是from memory cache | 不访问服务器!直接从硬盘中获取。浏览器关闭,资源不会被释放,数据依然存在,下次打开页面依然是from disk cache |
控制强制缓存的字段分别是Expires和Cache-Control,Cache-Control优先级比Expires高
http1.0规范,它设置一个值绝对时间的GMT格式的时间字符串,这个是资源失效时间(客户端的时间小于Expires的值),在这个时间之前都是名中缓存。
Expires:Mon,16 Oct 2066 23:59:59 GMT
缺陷:Expires控制缓存原理是客户端的时间和服务端返回的时间作对比,若两个时间偏差大的话,会造成强制缓存直接失效
http1.1规范,替代Expires,它利用的是相对时间,利用header信息字段的max-age值判断。
max-age=5000//代表资源的有效期是5000秒
除此之外还有常见的几个值
public | 可以被所有的用户缓存,包括终端用户和 CDN 等中间代理服务器 |
---|---|
private | 只能被终端用户缓存,不允许CDN等中间缓存器对其缓存(默认取值) |
no-cache | 客户端缓存,发送请求到服务器确实是否使用协商 |
no-store | 禁止缓存,级禁止强缓存和协商缓存,每次都需要重新请求数据 |
max-age | 缓存内容有效时间 |
Cache-Control的优先级比Expires高,Expires是绝对时间,Cache-Control是相对时间
向服务器发起请求,服务器根据这个请求的Request header的一些参数来判断是否命中协商缓存;命中返回304状态码并且会带上新的response header告诉浏览器可以从缓存中读取资源。没有命中返回200状态码和请求的结果。
协商换头字段Last-Modified/If-Modified-Since 和ETag/If-None-Match是成对出现的,呈现一一对应的关系
Last-Modified/If-Modified-Since 是http1.0的头字段,ETag/If-None-Match是http1.1的头字段
Etag / If-None-Match优先级高于Last-Modified / If-Modified-Since,同时存在则只有Etag / If-None-Match生效
一些概念
①Last-Modified
浏览器向服务器发送资源最后的修改时间
②If-Modified-Since
当资源过期时,发现响应头具有Last-Modified声明,则再次向服务器请求时带上头if-modified-since,表示请求时间。服务器收到请求后,发现有if-modified-since则与被请求资源的最后修改时间进行对比(Last-Modified),若最后修改时间较新,说明资源又被改过,则返回最新资源,返回200;若最后修改时间较小,说明资源无新修改,返回304 ,使用缓存文件。
③ETag
http1.1属性,由服务器生成返回给前端,帮助服务器控制web端的缓存验证,服务器会生成并且返回当前资源文件的一个唯一标识
④If-None-Match
当资源过期时,发现响应头具有Etag声明,则再次向服务器请求时带上头if-none-match(唯一标识Etag值)。服务器收到该请求后,发现有If-None-Match则根据If-None-Match的字段值与该资源在服务器的Etag值做对比,一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200。
Etag为什么会出现?
Last-Modified/If-Modified-Since有个缺陷,在短时间内变化,Last-Modified并不会发生变化。在周期性内变化,一个周期内修改为原来的样子,还是可以使用缓存,但是Last-Modified不是这么工作的,所以Etag出现了。
Last-Modify/If-Modify-Since 和ETag/If-None-Match的区别
①强缓存不发送请求到服务器,协商缓存发送请求到服务器
②强缓存资源更新浏览器不知道,因为没有发送请求到服务器;协商缓存资源更新浏览器都知道,因为发送了请求到服务器
③大部分web默认用协商缓存
当浏览器再次访问一个资源
①看是否命中强缓存,命中使用强缓存
②没有命中强缓存,发送请求到服务器看是否命中协商缓存
③若命中协商缓存,服务器返回304告诉浏览器可以使用本地缓存
④没有命中协商缓存,返回最新的资源
①当ctrl+f5强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存
②当f5刷新网页时,跳过强缓存,检查协商缓存
③浏览器地址栏中写入URL,不用请求直接走缓存,最快的速度