一、概述
前端缓存也就是HTTP缓存机制是前端性能优化很重要的一点,而前端本地存储和缓存却是不一样的,但对于新手的确有弄混淆的可能。本文详细记录它们的概念与特点
二、HTTP缓存
HTTP缓存,可以从缓存位置,获取缓存方式来学习
缓存位置
- service worker
- Memory Cache
- Disk Cache
- Push Cache
查找缓存优先级会依次从上到下匹配,如果都没命中那么才会去请求网络资源
service worker
一个服务器与浏览器之间的中间人角色,如果网站中注册了service worker那么它可以拦截当前网站所有的请求,进行判断(需要编写相应的判断程序),如果需要向服务器发起请求的就转给服务器,如果可以直接使用缓存的就直接返回缓存不再转给服务器。从而大大提高浏览体验。
- 使用 Service Worker,传输协议必须为 HTTPS
- 可以让开发者自己控制管理缓存的内容以及版本
- Service worker运行在worker上下文 --> 不能访问DOM
- 它设计为完全异步,同步API(如XHR和localStorage)不能在service worker中使用
- 其生命周期与页面无关(关联页面未关闭时,它也可以退出,没有关联页面时,它也可以启动)
Memory Cache
内存中的缓存,主要包含的是当前中页面中已经抓取到的资源,例如页面上已经下载的样式、脚本、图片等。读取内存中的数据肯定比磁盘快,内存缓存虽然读取高效,可是缓存持续性很短,会随着进程的释放而释放。一旦我们关闭 Tab 页面,内存中的缓存也就被释放了。
内存缓存在缓存资源时并不关心返回资源的HTTP缓存头Cache-Control是什么值,同时资源的匹配也并非仅仅是对URL做匹配,还可能会对Content-Type,CORS等其他特征做校验。
Disk Cache
Disk Cache就是存储在磁盘中的缓存,从存取效率上讲是比内存缓存慢的,但是他的优势在于存储容量和存储时长。一般来说查到的观点是比较大的js、CSS文件会直接被丢进磁盘,反之丢进内存;内存使用率比较高的时候,文件优先进入磁盘。而在实际缓存使用中,Disk Cache 覆盖面基本是最大的
Push Cache
Push Cache(推送缓存)是 HTTP/2 中的内容,当以上三种缓存都没有命中时,它才会被使用。它只在会话(Session)中存在,一旦会话结束就被释放,并且缓存时间也很短暂,在Chrome浏览器中只有5分钟左右,同时它也并非严格执行HTTP头中的缓存指令。
获取缓存方式
浏览器第一次向服务器发起该请求后拿到请求结果后,将请求结果和缓存标识存入浏览器缓存,浏览器对于缓存的处理是根据第一次请求资源时返回的响应头来确定的
强缓存
满足获取缓存条件情况下,不会向服务器发送请求,直接从缓存中读取资源
Expires
Expires即过期时间,存在于服务端返回的响应头中,告诉浏览器在这个过期时间之前可以直接从缓存里面获取数据,无需再次请求。但是服务端时间和客户端时间可能有误差,这也将导致缓存命中的误差,所以在HTTP1.1被Cache-Control替代,现在一般用于兼容
Cache-Control
Cache-Control有很多属性,不同的属性代表的意义也不同,可以多个命令配合灵活使用。
协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,协商缓存可以通过设置两种 HTTP Header 实现:Last-Modified 和 ETag 。
协商缓存需要进行对比判断是否可以使用缓存。浏览器第一次请求数据时,服务器会将缓存标识与数据一起响应给客户端,客户端将它们备份至缓存中。再次请求时,客户端会将缓存中的标识发送给服务器,服务器根据此标识判断。若未失效,返回304状态码,浏览器拿到此状态码就可以直接使用缓存数据了
Last-Modified
服务器在响应请求时,会告诉浏览器资源的最后修改时间。
if-Modified-Since: 浏览器再次请求服务器的时候,请求头会包含此字段,后面跟着在缓存中获得的最后修改时间。服务端收到此请求头发现有if-Modified-Since,则与被请求资源的最后修改时间进行对比,如果一致则返回304和响应报文头,浏览器只需要从缓存中获取信息即可。 从字面上看,就是说:从某个时间节点算起,是否文件被修改了
- 如果真的被修改:则响应资源内容,服务器返回:200 OK
- 如果没有被修改:服务器返回:304 Not Modified
ETag
服务器响应请求时,通过此字段告诉浏览器当前资源在服务器生成的唯一标识(生成规则由服务器决定)
If-None-Match: 再次请求服务器时,浏览器的请求报文头部会包含此字段,后面的值为在缓存中获取的标识。服务器接收到次报文后发现If-None-Match则与被请求资源的唯一标识进行对比。
- 不同,说明资源被改动过,则响应资源内容,服务器返回:200 OK
- 相同,说明资源无修改,服务器返回:304 Not Modified
对比
-
精确性,Etag要优于Last-Modified
-
性能上,Etag要差于Last-Modified,Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值。
-
Etag / If-None-Match优先级高于Last-Modified / If-Modified-Since,同时存在则只有Etag / If-None-Match生效。
用户行为对缓存的影响
- 地址栏回车:强缓存与协商缓存均有效
- 页面链接跳转:强缓存与协商缓存均有效
- 新开窗口:强缓存与协商缓存均有效
- F5刷新:强缓存无效,协商缓存有效
- Ctrl+F5刷新:强缓存与协商缓存均无效
缓存优点
- 减少了冗余的数据传递,节省宽带流量
- 减少了服务器的负担,大大提高了网站性能
- 加快了客户端加载网页的速度
三、本地存储
前端本地存储有cookie、localStorage 、 sessionStorage、IndexedDB等等,但常用的也就cookie、localStorage 、 sessionStorage。所以可以直接分析这三种本地存储的特性,可以从存储大小、数据有效性、作用域、通信来对比
常用本地存储的对比
存储大小
- cookie:一般不超过4K(因为每次http请求都会携带cookie、所以cookie只适合保存很小的数据,如会话标识)
- sessionStorage、localStorage:一般认为是5M或者更大,取决浏览器
数据有效性
- cookie:一般由服务器生成,可以设置失效时间;若没有设置时间,关闭浏览器cookie失效,若设置了时间,cookie就会存放在硬盘里,过期才失效
- sessionStorage:仅在当前浏览器窗口关闭之前有效,关闭页面或者浏览器会被清除
- localStorage:永久有效,窗口或者浏览器关闭也会一直保存,除非手动永久清除,因此用作持久数据
作用域
- cookie:在所有同源窗口中都是共享的
- sessionStorage:在同一个浏览器窗口是共享的(不同浏览器、同一个页面也是不共享的)
- localStorage:在所有同源窗口中都是共享的
通信
- ccokie:自动携带在同源的http请求中,即使不需要,故cookie在浏览器和服务器之间来回传递;如果使用cookie保存过多数据会造成性能问题
- sessionStorage、localStorage:仅在客户端(即浏览器)中保存,不参与和服务器的通信;不会自动把数据发送给服务器,仅在本地保存
总结
cookie与Web Storage包括其他本地存储各有优缺点,比如cookie容量太小,存在安全缺陷并且有一定的性能缺陷,Web Storage作为为了本地存储而诞生,所以无法参与通信,还有例如IndexDB等,兼容性还不是很好,所以我们需要在合适的场景灵活选择