🗔浏览器/HTTP缓存机制

在Web开发中,与HTTP协议打交道是必不可少的!

HTTP协议支持缓存机制,并最终由浏览器实现并使用,我们以此作为关注点,来探究以下两个问题:

  • HTTP协议中如何支持缓存?
  • 具体的工作流程如何?

概述

HTTP 缓存会存储与请求关联的响应,并将存储的响应复用于后续请求。

复用的优点显而易见:

  • 不需要将请求传递到服务器,响应速度快;
  • 服务器不需要处理业务逻辑,降低了服务器的负载;

在许多其他文章中,作者常常直接介绍强缓存,协商缓存的工作机制,我觉得这样知识的构建过程不够流畅,因此下文我将基于前面提出的两个问题,由浅入深的进行阐述,如有问题欢迎大家指正!

HTTP协议中如何支持缓存?

一句话回答:在Http协议中,规定了很多HTTP请求报文和响应报文的头信息,而在这些头信息中,有很多字段就是用来支持缓存的,这些字段仅仅是依照HTTP协议的规定来表示当前请求/响应的缓存规则,而浏览器和服务器的HTTP模块则是依据协议规定进行开发的!

既然我们知道了HTTP缓存是通过头字段来告知浏览器/中间服务器如何缓存响应了,那么我们就需要学习相关字段了!

头字段

以下所介绍的都是有关HTTP缓存的头字段;

  • Expires
    • 响应头字段;
    • 包含日期/时间,即在此时候之后,响应过期,如果值为无效值,则表示已过期;
    • 优先级低于Cache-Control字段
  • Cache-Control
    • 优先级高于Expires字段
    • 通用消息头字段;
    • 可设置多种配置项,主要如下:
      • max-age=<seconds> : 由服务器设置,设置该响应的最大缓存时间(单位:s),时间是相对于请求的时间;
      • public:表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存;
      • private:表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它);注意: 如果响应具有 Authorization 标头,则不能进行缓存,因为响应一般包含用户私有的令牌/凭证/密码等信息;
      • no-cache:在使用缓存前询问源头服务器内容是否发生变化,并根据结果选择是否使用缓存;
      • no-store: 不使用缓存;
  • Last-Modified:是一个响应 头字段,其中包含源头服务器认定的资源做出修改的日期及时间;当与 If-None-Match一同出现时,它会被忽略掉,除非服务器不支持 If-None-Match
  • If-Modified-Since:是一个条件式请求 头字段,服务器只在所请求的资源在给定的日期时间之后对内容进行过修改的情况下才会将资源返回,状态码为200。如果请求的资源从那时起未经修改,那么返回一个不带有消息主体的 304 Not Modified响应,而在Last-Modified首部中会带有上次修改时间;
    • 客户端会将对应资源上次响应的Last-Modified值设置为下一次询问时If-Modified-Since的值;
  • E-Tag
    • 响应头字段
    • 用于指定该资源的版本,是资源版本标识符
    • 服务端通过设置E-Tag来标识资源版本,请求端通常会将接收到的E-Tag值设置为If-None-Match的值发往服务端,服务端通过If-None-Match来判断资源是否更改并类似于If-Modified-Since一样返回200304
  • If-None-Match: <etag_value>

具体的工作流程如何?

在学习了解了HTTP协议中有关缓存的部分头字段后,我们接下来要了解一下Cache-ControlE-tag 字段具体的工作流程:

源头服务器设置Cache-Control流程:

E-tag使用流程:

事实上,这两个字段的工作流程就引出了两种缓存策略:强缓存、协商缓存,他们可以组合使用,同步起效!

强缓存

强缓存实际上就是不去确认当前这个资源是否更新,仅通过第一次请求该资源时所获得的响应中的Cache-ControlExpires字段来确认该资源是否可以重用;

但是如果强缓存判断时资源已经过期了,就会经过协商缓存的步骤!

协商缓存

协商缓存实际上就是当某个资源没有配置强缓存或强缓存过期时,我们需要向服务端验证本地缓存的资源是否可以复用的过程。

  • 当强缓存过期后,浏览器会将该请求发往服务端,但是会携带资源对应的If-None-Match:<etag-value>If-Modified-Since头字段信息
  • 服务端首先会验证资源是否可以重用从而进行响应:200代表缓存不可用,304代表未更新,可使用缓存数据;

缓存存储在哪

你可以在开发者工具中的网络页签中看到,有些缓存的请求来自内存(memory cache),而有些请求来自硬盘(disk cache)

缓存的存储与你访问的页面URL相关联,当你第一次请求到一个缓存资源后,他将存储在内存中,此时如果你刷新页面,会发现很多请求的来源都是来自内存的!一旦你关闭了页签,再次重新打开时会发现他们又都大多来自硬盘了!

总结

浏览器对资源进行缓存的依据是由HTTP协议中规定的各个字段所决定的;

强缓存所涉及的字段:

  • Cache-Control Expires;
  • 浏览器会优先判断 Cache-Control

协商缓存所涉及的字段:

  • If-Modified-Since & Last-Modified
  • E-Tag & If-None-Match
  • 服务端会优先判断If-None-Match,如果无该字段才会使用If-Modified-Since;

浏览器发送请求前会先判断强缓存是否可用, 如果不可用则发送请求询问协商缓存是否可用!

参考

相关推荐
m0_7482361123 分钟前
Calcite Web 项目常见问题解决方案
开发语言·前端·rust
Watermelo61735 分钟前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
m0_7482489437 分钟前
HTML5系列(11)-- Web 无障碍开发指南
前端·html·html5
m0_748235611 小时前
从零开始学前端之HTML(三)
前端·html
一个处女座的程序猿O(∩_∩)O3 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
hackeroink6 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
LCG元7 小时前
【面试问题】JIT 是什么?和 JVM 什么关系?
面试·职场和发展
迷雾漫步者7 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-8 小时前
验证码机制
前端·后端
燃先生._.9 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js