摘要:整个请求响应链的缓存机制必须遵循的特别指令。基本的缓存机制就是由这些参数形成的。如果此文章中有什么问题的话,烦请一定要指出,谢谢参考资料缓存机制浅析移动端加载性能优化浅谈浏览器的缓存机制
之前对http的缓存知识一知半解,只能说出个大概。和同事交流这块内容时稍一深入探讨就捉襟见肘,自惭形秽。故痛定思痛,花了一两天时间去研究了下这块内容,写下这篇笔记方便以后的查询与修正。
首先介绍下和缓存相关的http头字段参数。http的头字段包括通用头字段(general-header)、请求头字段(request-header)、响应头字段(response-header)以及实体头字段(entity-header)。
我个人对实体头字段这个说法有点陌生,所以查阅了相关资料:根据RFC-2616(7.1 Entity Header Fields)中的解释是:实体头字段(entity header)定义了实体主体(entity-body)的元信息,如果实体主体(entity-body)不存在,则表示http请求所标识的资源的元信息。
general headerEntity-header fields define metainformation about the entity-body or,
if no body is present, about the resource identified by the request.
Cache-Control: 整个请求响应链的缓存机制必须遵循的特别指令。这个指令是单向的,因为请求中该指令的效果和响应中的效果并不一样。其值包括max-age,no-cache等。
The Cache-Control general-header field is used to specify directives that MUST be obeyed by all caching mechanisms along the request/response chain.
Cache directives are unidirectional in that the presence of a directive in a request does not imply that the same directive is to be given in the response.
Date: 请求或响应的时间和日期。(注:这里的日期格式使用的是GMT格式,即格林威治时间,要换算成北京时间的话要加上8小时)
Pragma:可被应用到整个请求响应链中的自定义设置,例如:Pragma: no-cache。
request headerThe Pragma general-header field is used to include implementation-specific directives that might apply to any recipient along the request/response chain.
If-Modified-Since: 如果从该参数指定的时间开始,请求并没有被修改的话,服务器会返回304(not modified)状态码,而不是一个实体。
if the requested variant has not been modified since the time specified in this field, an entity will not be returned from the server; instead, a 304 (not modified) response will be returned without any message-body.
If-Unmodified-Since: 如果从该参数指定的时间开始,请求并没有被修改的话,服务器应该执行请求的操作。如果被修改过的话,服务器不执行操作病返回412(Precondition Failed)状态码
If the requested resource has not been modified since the time specified in this field, the server SHOULD perform the requested operation as if the If-Unmodified-Since header were not present.
If the requested variant has been modified since the specified time, the server MUST NOT perform the requested operation, and MUST return a 412 (Precondition Failed).
If-None-Match: 允许在对应的内容未被修改的情况下返回304未修改( 304 Not Modified ),判断依据为客户端该参数存储的Etag值与服务器上存储的Etag是否相匹配。(原文太长,暂时拿wiki百科来填坑)
If-Match: 仅当客户端提供的实体与服务器上对应的实体相匹配时,才进行对应的操作。主要用作像 PUT 这样的方法中,仅当从用户上次更新某个资源以来,该资源未被修改的情况下,才更新该资源。如果不匹配,则返回412(Precondition Failed)状态码,该参数也会被忽略。(原文太长,暂时拿wiki百科来填坑)
response headerETag: 指定请求变量的当前实体Tag。该字段用来比较来自同一资源的变化的实体。(只是直译,后面会有详细解释和用法)
Entity HeaderThe ETag response-header field provides the current value of the entity tag for the requested variant.
Expires: 指定过期时间。
The Expires entity-header field gives the date/time after which the response is considered stale.
Last-Modified: 指定了服务器认为资源最近一次修改的时间。
The Last-Modified entity-header field indicates the date and time at which the origin server believes the variant was last modified.
字段参数可能会有翻译或者理解错误,请各位大大指出。
了解了参数的含义后,接下来就是看具体的缓存机制了。
HTTP 1.0时代 (基于Pragma&Expires的缓存实现)Pragma在RFC1945文档中只提供了“no-cache”值,当"no-cache"出现在请求消息中时,应用程序应当向原始服务器推送此请求,即使它已经在上次请求时已经缓存了一份拷贝。这样将保证客户端能接收到最权威的回应。它也用来在客户端发现其缓存中拷贝不可用或过期时,对拷贝进行强制刷新。
(HTTP1.1会把请求中的pragma="no-cache"视为发送了Cache-Control: no-cache)
有Pragma用来禁用缓存的话,那就有Expires来设置缓存。
就如上文介绍所说,Expires是用来指定过期时间的,时间格式为GMT,如果客户端时间没有超过该时间点的话,则不发送请求。但是值得注意的是,Expires所定义的缓存时间是相对服务器上的时间而言的,如果客户端的时间和服务器的时间不一致的话(例如用户修改了系统时间),那么这个资源失效时间也没有意义了。
http1.1新增了 Cache-Control 来定义缓存过期时间,若报文中同时出现了Expires 和 Cache-Control,会以 Cache-Control 为准。
如上文介绍所说,Cache-Control是通用头部参数,格式为
"Cache-Control" ":" cache-directive
作为请求头部时,cache-directive的可选值为:(图片来自网络)
作为响应头部时,cache-directive的可选值为:(图片来自网络)
cache-control设置缓存的使用方法为:Cache-Control:max-age=31536000,缓存单位为秒。
如果客户端请求的资源未超过缓存时间,则直接取本地缓存,状态码为200(from memory cache),
但是如果超过缓存时间或者直接不走缓存的话,那我们就需要和其他的字段配合来校验缓存了。
服务端传递资源给客户端的时候会在响应报文中带上这个信息,而客户端接受到资源后会将该信息的值设置为请求头中If-Modified-Since参数的值(If-Modified-Since: Last-Modified value)。在下次发送请求的时候(max-age过期之后),会将请求头中的If-Modified-Since参数的值与服务端Last-Modified的值去比较,如果仍是一致的,那么说明该资源未被修改,直接返回304状态码即可,如果不一致,则返回状态码200,以及新的Last-Modified。
但是Last-Modified会有不准确的时候,比如服务端的资源做了无实际变化的修改(加一个空格再删掉),这样也会使服务端Last-Modified的时间更新,导致客户端请求中If-Modified-Since的值与其无法匹配,就会返回整个实体。(即使返回的实体内容与客户端的缓存内容没有区别)
2. EtagEtag是一种比Last-Modified更为精确的校验方式。服务器会通过某种算法,给资源计算得出一个唯一标志符。其判断依据和Last-Modified类似,只是服务端在传递资源给客户端的相应报文中带上Etag后,客户端会将其设置为请求头中If-None-Match参数的值(If-None-Match: Etag-value),然后在传递资源时进行比较。
如果同时使用Last-Modified和Etag进行验证的话,那么两者中有一个通过校验(即传递的值可以匹配),则可以认为资源并没有被修改。
基本的缓存机制就是由这些参数形成的。
最后我们来看下,不同的页面打开方式对缓存机制的影响
主要有以下两点要注意:
1.手动刷新页面(F5刷新),浏览器会直接认为缓存已经过期,即使缓存并没有过期,在请求中加上字段:Cache-Control:max-age=0,发包向服务器查询是否有文件是否有更新。
2.强制刷新页面(ctrl+F5刷新),浏览器会直接忽略本地缓存内容,即使本地有缓存可用,在请求中加上字段:Cache-Control:no-cache(或 Pragma:no-cache),发包向服务器重新请求文件。
其他的直接上图(图片来自网络):
此篇文章的很多想法是借鉴网上高手的文章,我会在底部标明参考出处。如果此文章中有什么问题的话,烦请一定要指出,谢谢!
参考资料
RFC2616
H5 缓存机制浅析 移动端 Web 加载性能优化
浅谈浏览器http的缓存机制
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/61822.html
摘要:浅谈网站性能之前端性能优化性能优化的目的无非是减少用户流量消耗,提升用户首屏体验,提升用户访问速度,让用户专注内容本身。前端性能优化减少请求数量基本原理在浏览器与服务器进行通信时,主要是通过进行通信。 最近项目慢慢走上正轨,需求趋于平稳,这才想起需要对整站进行性能优化。经过一段时间的学习,结合现在项目的实际性能情况,发现确实有许多地方可以进行优化。于是就开始了我的前端性能优化之旅。以下...
摘要:浅谈网站性能之前端性能优化性能优化的目的无非是减少用户流量消耗,提升用户首屏体验,提升用户访问速度,让用户专注内容本身。前端性能优化减少请求数量基本原理在浏览器与服务器进行通信时,主要是通过进行通信。 最近项目慢慢走上正轨,需求趋于平稳,这才想起需要对整站进行性能优化。经过一段时间的学习,结合现在项目的实际性能情况,发现确实有许多地方可以进行优化。于是就开始了我的前端性能优化之旅。以下...
摘要:例如,将获得最高优先级,而将获得低优先级或中优先级。不带属性的的优先级将会等同于异步请求。对使用属性,不然将不会从中获益。因此,在标记中声明以被扫描器扫描。 这是 Web 性能优化的第 6 篇,上一篇在下面看点击查看: Web 性能优化:使用 Webpack 分离数据的正确方法 Web 性能优化:图片优化让网站大小减少 62% Web 性能优化:缓存 React 事件来提高性能 We...
打算现在开始在博客里写点东西,也能为自己看过的书学过的知识做一个归纳总结。这几日拜读了Steve Souders的《高性能网站建设指南这本书》,虽然这本书可能已经有些老了,但薄薄的一个小册子里提出的网站性能优化的准则还是非常有价值的。这些规则都有个共同点,就是用很小的工作就能获得很明显的性能提升,性价比极高。废话不多说了,总结一下书里的几点性能优化规则。 首先有一点需要说明的是书中所写的性能黄金法...
阅读 882·2021-09-09 09:32
阅读 2767·2021-09-02 10:20
阅读 2630·2021-07-23 11:24
阅读 802·2019-08-30 15:54
阅读 3609·2019-08-30 15:54
阅读 1314·2019-08-30 11:02
阅读 2805·2019-08-26 17:40
阅读 1096·2019-08-26 13:55