Web缓存策略
关于Web 缓存
-
Web 缓存是指一个 Web 资源(如 html 页面,图片,js,数据等)存在于 Web 服务器和客户端(浏览器)之间的副本。
-
缓存会根据进来的请求保存输出内容的副本;当下一个请求来到的时候,如果是相同的 URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发送请求。
Web 缓存的好处
-
减少网络延迟,加快页面打开速度
-
减少网络带宽消耗
-
降低服务器压力
HTTP 的缓存机制
流程如图:
缓存规则:
-
过期机制:也就是缓存副本有效期。一个缓存副本必须满足以下条件,浏览器会认为它是有效的,足够新的:
-
含有完整的过期时间控制头信息(HTTP 协议报头),并且仍在有效期内;
-
浏览器已经使用过这个缓存副本,并且在一个会话中已经检查过新鲜度
2.校验值(验证机制):服务器返回资源的时候有时在控制头信息带上这个资源的实体标签 Etag(Entity Tag),它可以用来作为浏览器再次请求过程的校验标识。如果发现校验标识不匹配,说明资源已经被修改或过期,浏览器需求重新获取资源内容。
HTTP 缓存的两个阶段
浏览器缓存一般分为两类:强缓存(也称本地缓存)和协商缓存(也称弱缓存)。
本地缓存阶段
浏览器发送请求前,会先去缓存里查看是否命中强缓存,如果命中,则直接从缓存中读取资源,不会发送请求到服务器。否则,进入下一步。
协商缓存阶段
当强缓存没有命中时,浏览器一定会向服务器发起请求。服务器会根据 Request Header 中的一些字段来判断是否命中协商缓存。如果命中,服务器会返回 304 响应,但是不会携带任何响应实体,只是告诉浏览器可以直接从浏览器缓存中获取这个资源。如果本地缓存和协商缓存都没有命中,则从直接从服务器加载资源。
http缓存请求相应头
-
Cache-Control 请求/响应头,缓存控制字段,可以说是控制http缓存的最高指令,要不要缓存它说了算。它有以下常用值:
-
no-store
:表示当前请求资源禁用缓存 -
no-cache
:缓存,但是浏览器使用缓存前,都会请求服务器判断缓存资源是否是最新,它是个比较高贵的存在,因为它只用不过期的缓存。 -
max-age=x
(单位秒) 请求缓存后的X秒不再发起请求,属于http1.1属性,与下方Expires(http1.0属性)类似,但优先级要比Expires高。会覆盖expires -
s-maxage=x
(单位秒) 代理服务器请求源站缓存后的X秒不再发起请求,只对CDN缓存有效,比如,当s-maxage=60时,在这60秒中,即使更新了CDN的内容,浏览器也不会进行请求。也就是说max-age用于普通缓存,而s-maxage用于代理缓存。如果存在s-maxage,则会覆盖掉max-age和Expires header。 -
public
客户端和代理服务器(CDN)都可缓存 -
private:表示只有用户自己的浏览器能够进行缓存,公共的代理服务器不允许缓存
响应头,代表资源过期时间,由服务器返回提供,GMT格式日期,是http1.0的属性,在与max-age(http1.1)共存的情况下,Cache-Control 优先级高于 Expires,为了兼容,通常两个头部同时设置.
Response Header 中沒有设置 Cache-Control 和 Expires,浏览器仍然会缓存某些资源,这是浏览器的默认行为,是为了提升性能进行的优化,每个浏览器的行为可能不一致,有些浏览器甚至没有这样的优化
3 Last-Modified
响应头,资源最新修改时间,由服务器告诉浏览器。
4 if-Modified-Since
请求头,资源最新修改时间,由浏览器告诉服务器(其实就是上次服务器给的Last-Modified,请求又还给服务器对比),和Last-Modified是一对,它两会进行对比。
5 Etag
ETag 是一个响应首部字段,它是根据实体内容生成的一段 hash 字符串,标识资源的状态,由服务端产生。If-None-Match 是一个条件式的请求首部。如果请求资源时在请求首部加上这个字段,值为之前服务器端返回的资源上的 ETag,则当且仅当服务器上没有任何资源的 ETag 属性值与这个首部中列出的时候,服务器才会返回带有所请求资源实体的 200 响应,否则服务器会返回不带实体的 304 响应。
使用ETag可以解决Last-modified存在的一些问题:
a、某些服务器不能精确得到资源的最后修改时间,这样就无法通过最后修改时间判断资源是否更新
b、如果资源修改非常频繁,在秒以下的时间内进行修改, Last-Modified 标注的最后修改只能精确到秒级
c、一些资源的最后修改时间改变了,但是内容没改变,但 Last-Modified 却改变了,导致文件没法使用缓存。
6 if-None-Match
请求头,缓存资源标识,ETag 与 If-None-Match 是一对报文头。
常见的几种刷新场景
1.当 F5 刷新网页时,跳过强缓存,但是会检查协商缓存
2.当 Ctrl + F5 强制刷新页面时,直接从服务器加载,跳过强缓存和协商缓存
3.浏览器地址栏回车等这些行为,会让Expires,max-age生效,也就是说,浏览器会判断过期时间,再考虑要不要发起请求,当然Last-Modified和Etag也有效。
其他web缓存策略
IndexDB
IndexedDB 就是浏览器提供的本地数据库,能够在客户端存储可观数量的结构化数据,并且在这些数据上使用索引进行高性能检索的 API。
LocalStorage
localStorage 属性允许你访问一个 Document 源(origin)的对象 Storage 用于存储当前源的数据,除非用户人为清除(调用 localStorage api 或则清除浏览器数据), 否则存储在 localStorage 的数据将被长期保留。
SessionStorage
sessionStorage 属性允许你访问一个 session Storage 对象,用于存储当前会话的数据,存储在 sessionStorage 里面的数据在页面会话结束时会被清除。页面会话在浏览器打开期间一直保持,并且重新加载或恢复页面仍会保持原来的页面会话。
定义最优缓存策略
-
使用一致的网址:如果您在不同的网址上提供相同的内容,将会多次获取和存储该内容。注意:URL 区分大小写!
-
确定中继缓存可以缓存哪些资源:对所有用户的响应完全相同的资源很适合由 CDN 或其他中继缓存进行缓存;
-
确定每个资源的最优缓存周期:不同的资源可能有不同的更新要求。审查并确定每个资源适合的 max-age;
-
确定网站的最佳缓存层级:对 HTML 文档组合使用包含内容特征码的资源网址以及短时间或 no-cache 的生命周期,可以控制客户端获取更新的速度;
-
更新最小化:有些资源的更新比其他资源频繁。如果资源的特定部分(例如 JS 函数或一组 CSS 样式)会经常更新,应考虑将其代码作为单独的文件提供。这样,每次获取更新时,剩余内容(例如不会频繁更新的库代码)可以从缓存中获取,确保下载的内容量最少;
-
确保服务器配置或移除 ETag:因为 Etag 跟服务器配置有关,每台服务器的 Etag 都是不同的;
-
善用 HTML5 的缓存机制:合理设计启用 LocalStorage、SessionStorage、IndexDB、SW 等存储,会给页面性能带来明显提升;
-
结合 Native 的强大存储能力:善于利用客户端能力,定制合适的缓存机制,打造极致体验。