前端-web缓存

为什么需要缓存

本文重点介绍浏览器缓存,服务端等缓存不是本文重点

 

首先从原始的前端开发讲起,上图是一个“可爱”的index.html页面和它的样式文件a.css,用文本编辑器写代码,无需编译,本地预览,确认OK,丢到服务器,等待用户访问。前端就是这么简单,好好玩啊,门槛好低啊,分分钟学会有木有!


然后我们访问页面,看到效果,再查看一下网络请求,200!不错,太™完美了!那么,研发完成。。。。了么?等等,这还没完呢!对于大公司来说,那些变态的访问量和性能指标,将会让前端一点也不“好玩”。看看那个a.css的请求吧,如果每次用户访问页面都要加载,是不是很影响性能,很浪费带宽啊,我们希望最好这样


利用304,让浏览器使用本地缓存。但,这样也就够了吗?不成!304叫协商缓存,这玩意还是要和服务器通信一次,我们的优化级别是变态级,所以必须彻底灭掉这个请求,变成这样:


强制浏览器使用本地缓存(cache-control/expires),不要和服务器通信。好了,请求方面的优化已经达到变态级别,那问题来了:你都不让浏览器发资源请求了,这缓存咋更新?以百度和bing的首页为例,index.html也就是入口地址要禁止缓存,然后通过更新页面中引用的资源路径,让浏览器主动放弃缓存,加载新资源。如何更改引用资源路径不是本文重点,感兴趣的童鞋可以自行查阅资料,以后我也会更新。

 

 

协商缓存和强缓存

  • 强缓存:浏览器在加载资源时,先根据这个资源的一些http header判断它是否命中强缓存,强缓存如果命中,浏览器直接从自己的缓存中读取资源,不会发请求到服务器。比如某个css文件,如果浏览器在加载它所在的网页时,这个css文件的缓存配置命中了强缓存,浏览器就直接从缓存中加载这个css,不会发送请求到服务器,也就是上图中的from memory cache,谷歌浏览器是个特殊的存在,有from memory cache和from disk cache,(假设你已经使用过百度,以百度首页为例)当你关闭浏览器,再次打开进入百度首页时,会触发from disk cache,此时刷新浏览器,会触发from memory cache,此时内容已经加载到浏览器内存中,谷歌浏览器选择直接从内存中读取

     

    disk cache

     

    memory cache

  • 协商缓存:当强缓存没有命中的时候,浏览器一定会发送一个请求到服务器,服务器端依据资源的另外一些http header验证这个资源是否命中协商缓存,如果协商缓存命中,服务器会将这个请求返回(304),但是不会返回这个资源的数据,而是告诉客户端可以直接从缓存中加载这个资源,于是浏览器就又会从自己的缓存中去加载这个资源;若未命中请求,则将资源返回客户端,并更新本地缓存数据(200)。

强缓存与协商缓存区别:强缓存不会发请求到服务器,协商缓存会发请求到服务器。

设置缓存

  • HTML Meta标签控制缓存(非HTTP协议定义)
    <META HTTP-EQUIV="Pragma" CONTENT="no-cache">等等
    上述代码的作用是告诉浏览器当前页面不被缓存,每次访问都需要去服务器拉取。这种方法使用上很简单,但只有部分浏览器可以支持,而且所有缓存代理服务器都不支持,因为代理不解析HTML内容本身。
  • HTTP头信息控制缓存
    HTTP头信息控制缓存是通过Expires(强缓存)、Cache-control(强缓存)、Last-Modified/If-Modified-Since(协商缓存)、Etag/If-None-Match(协商缓存)实现,下面详细介绍。

expires

Expires是http1.0提出的一个表示资源过期时间的header,它描述的是一个绝对时间,由服务器返回,用GMT格式的字符串表示,如:Expires:Thu, 31 Dec 2016 23:55:55 GMT
读取缓存数据条件:缓存过期时间(服务器)< 当前时间(客户端)
缺点:Expires是较老的强缓存管理header,由于它是服务器返回的一个绝对时间,这样存在一个问题,如果客户端的时间与服务器的时间相差很大(比如时钟不同步,或者跨时区),那么误差就很大,所以在HTTP 1.1版开始,使用Cache-Control: max-age=秒替代。

cache-control

Cache-Control描述的是一个相对时间,在进行缓存命中的时候,都是利用客户端时间进行判断,所以相比较Expires,Cache-Control的缓存管理更有效,安全一些。
读取缓存数据条件:上次缓存时间(客户端)+max-age < 当前时间(客户端)
Cache-Control值可以是public、private、no-cache、no- store、no-transform、must-revalidate、proxy-revalidate、max-age

各个消息中的指令含义如下:
Public指示响应可被任何缓存区缓存。
Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当前用户的部分响应消息,此响应消息对于其他用户的请求无效。
no-cache指示请求或响应消息不能缓存,该选项并不是说可以设置”不缓存“,而是需要和服务器确认
no-store在请求消息中发送将使得请求和响应消息都不使用缓存,完全不存下來。
max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。上次缓存时间(客户端的)+max-age(64200s)<客户端当前时间
min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。
max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。
注意:这两个header可以只启用一个,也可以同时启用,当response header中,Expires和Cache-Control同时存在时,Cache-Control优先级高于Expires

Last-Modified/If-Modified-Since

Last-Modified/If-Modified-Since要配合Cache-Control使用。
Last-Modified:标示这个响应资源的最后修改时间。web服务器在响应请求时,告诉浏览器资源的最后修改时间。
If-Modified-Since:当资源过期时(强缓存失效),发现资源具有Last-Modified声明,则再次向web服务器请求时带上头 If-Modified-Since,表示请求时间。web服务器收到请求后发现有头If-Modified-Since 则与被请求资源的最后修改时间进行比对。若最后修改时间较新,说明资源又被改动过,则响应整片资源内容(写在响应消息包体内),HTTP 200;若最后修改时间较旧,说明资源无新修改,则响应HTTP 304 (无需包体,节省浏览),告知浏览器继续使用所保存的cache。
缺点:

  • Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间(无法及时更新文件)
  • 如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存,有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形(无法使用缓存)。

Etag/If-None-Match

为了解决Last-Modified的问题,HTTP1.1中引入了Etag,Etag/If-None-Match也要配合Cache-Control使用
Etag:web服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定)。Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。
If-None-Match:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Etage声明,则再次向web服务器请求时带上头If-None-Match (Etag的值)。web服务器收到请求后发现有头If-None-Match 则与被请求资源的相应校验串进行比对,决定返回200或304。
Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified与ETag一起使用时,服务器会优先验证ETag。

大厂的缓存设置

以百度和必应为例,百度同时使用了expires和cache control,etag和Last-Modified,而必应只使用了cache-control,Last-Modified。
使用时,可以根据自己的场景设置。

 

百度首页

 

必应首页

用户行为与缓存

用户操作Expires/Cache ControlLast-Modified/Etag
地址栏回车有效有效
页面链接跳转有效有效
新开窗口有效有效
前进/后退有效有效
F5/按钮刷新无效,浏览器重置max-age=0有效
Ctrl+F5无效重置cache-control: no-cache无效,请求头丢弃该选项

然而上表并不完全准确,比如谷歌chrome这个神奇的存在,笔者使用的66版本,F5刷新,并不会重置max-age=0,依然命中强缓存,但是linux中使用的chrome 50版本则会重置max-age=0

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编写高质量的Web前端代码是每个前端开发者都应该努力追求的目标。以下是一些关键要点,帮助我们编写高质量的Web前端代码: 1. 代码结构和组织:良好的代码结构和组织是编写高质量代码的基础。我们应该遵循一致的命名规范,使用有意义的变量和函数名称,并将相关的代码块分组和组织好。 2. 可维护性:代码应该易于理解和维护。可以通过添加适当的注释和文档来帮助其他开发者快速理解代码的功能和目的。 3. 性能优化:前端性能是用户体验的重要组成部分。我们应该考虑减少HTTP请求、压缩和缓存静态资源、使用合适的数据结构和算法等方法来优化代码性能。 4. 交互和用户体验:编写高质量的代码还包括提供良好的用户体验。我们应该确保网页的交互和响应能够符合用户的期望,并考虑到不同终端和浏览器的兼容性。 5. 安全性:在开发Web应用时,我们需要关注安全性。应该采取必要的措施来防止常见的Web安全漏洞,如跨站脚本攻击(XSS)和跨站请求伪造(CSRF)。 6. 测试和调试:编写高质量代码还包括进行适当的测试和调试。我们应该编写单元测试来确保代码的正确性,使用浏览器开发者工具来快速定位和解决问题。 7. 学习和持续改进:Web前端技术在不断发展和演变,作为开发者,我们应该不断学习和掌握新的技术和最佳实践,以保持代码的质量和效率。 总而言之,编写高质量的Web前端代码需要综合考虑代码结构、可维护性、性能、用户体验、安全性、测试和调试等多个方面。通过不断学习和实践,我们可以不断改进自己的编码技巧,提高代码的质量和效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值