浏览器缓存机制(详)

news2024/9/21 23:43:25

目录

  • 1,缓存的分类
    • 1.1,按缓存位置
      • 1,Service Worker
      • 2,Memory Cache
      • 3,Disk Cache
      • 4,Push Cache
    • 1.2,按缓存类型
      • 强缓存
        • Expires
        • Cache-control
      • 协商缓存
        • Last-Modified & If-Modified-Since
        • Etag & If-None-Match
  • 2,缓存读取规则
  • 3,浏览器的一些行为
  • 4,缓存最佳实践
    • 频繁变动的资源
    • 不常变化的资源

1,缓存的分类

1.1,按缓存位置

1,Service Worker

MDN参考

它是运行在浏览器后台的独立线程,可以将它理解为是一个代理服务器。可以拦截所有的网络请求,也可以缓存数据。主要是为了创建有效的离线体验,比如后台同步,离线渲染,推送通知等。

它的缓存机制也比较特殊,可以自由的控制:缓存内容,匹配规则,读取规则,有效期等。

实现缓存的大致步骤:

  • 注册 Service Worker。
  • 监听 install 事件提前缓存资源。
  • 监听 fetch 事件,拦截网络请求并返回已缓存的资源。

在这里插入图片描述

2,Memory Cache

它是内存中的缓存,主要缓存当前页面中已经抓取到的资源,例如已经下载的样式、脚本、图片等,保存一份资源的引用,以备下次使用。

注意,Memory Cache 是浏览器为了加快读取缓存速度而进行的自身的优化行为,不受开发者控制,也不受 HTTP Header 的约束,算是一个黑盒。

访问页面后,再次刷新,可以看到很多数据来自内存缓存:
在这里插入图片描述

特点:读取速度快,但时效性很短,会随着进程结束而释放。比如关闭标签页,内存中的缓存就被释放了。

而因为计算机可使用的内存一般都比较小,操作系统对内存的使用会更精细化,所以可供浏览器使用的并不会很多。

作用:该缓存机制保证了一个页面有2个以上相同的资源请求时,实际最多只会被请求一次,如上图所示。

3,Disk Cache

重点

它是存储在硬盘中的缓存,是覆盖面最大的缓存机制,会根据 HTTP Header 中的字段(Cache-Control等)来判断:

  • 哪些资源需要缓存
  • 哪些资源可以不请求直接使用
  • 哪些资源已经过期需要重新请求

并且在跨站点的情况下,相同地址的资源一旦被硬盘缓存下来,就不会再去请求数据。一般来说,绝大部分缓存都来自 Disk Cache

特点:读取速度较慢,但时效性很好(可设置)。

因为时效性的原因,Disk Cache 也算是持久性存储,所以也会面对容量增长的问题。

而浏览器解决这个问题,是通过特殊的算法把 “最老的” 和 “最有可能过时” 的资源一个一个的删除。

4,Push Cache

称为推送缓存或启发式缓存,是HTTP2 新增的内容。

上面3种缓存都没有命中时,它才会被使用,并且时效性很短,只在 session 会话中存在,会话结束就被释放了。

这个我了解的不多,网上也没有找到合适的文章,就不多做介绍了。

1.2,按缓存类型

其实是对 Disk Cache 进行的分类。

强缓存

当浏览器请求资源后,会优先访问强缓存。存在则返回,否则请求服务器,响应后再次写入强缓存。

作用:直接减少请求数量,是提升最大的缓存策略。通过缓存优化网页性能时是应该首先被考虑的。

实现:通过 HTTP Header 中的字段:ExpiresCache-control

Expires

是 HTTP 1.0 的字段,表示缓存到期的时间,是一个绝对时间(当前时间+缓存时间)

Expires: Wed, 20 Dec 2023 23:09:07 GMT

响应头中设置该字段,告诉浏览器在过期之前不要再次请求。

但是这个字段有明显的缺点:

  • 写法复杂,不利于解析。一旦缺少字母或空格就会变为非法属性而失效。

对比正常的时间格式

new Date() // Wed Dec 20 2023 23:09:07 GMT+0800 (中国标准时间)
new Date('Wed Dec 20 2023 23:09:07 GMT+0800') // Wed Dec 20 2023 23:09:07 GMT+0800 (中国标准时间)
  • 由于是绝对时间,用户可以修改本地时间,导致浏览器判断缓存失效而重新请求资源。
    即便不考虑本地修改的问题,时间误差等因素也会导致浏览器和服务器之间的时间不一致,导致缓存失效。
Cache-control

在已知 Expires 的缺点后,在 HTTP 1.1 中增加该字段,是一个相对时间,表示资源缓存的最大有效时间,该时间内不需要再次向服务器发送请求。

Cache-Control: max-age=3600

下面列举一些 Cache-control 的常用值,更多的字段参考 MDN

  • max-age,最大有效时间

  • must-revalidate(响应头信息),如果超过了 max-age 的时间,浏览器必须向服务器发送请求,验证资源是有效性。

  • no-cache,客户端会缓存资源,但每次都得发送请求验证有效性,等价于 max-age=0 must-revalidate

  • no-store,真正意义上的“不要缓存”。所有内容都不走缓存,包括强缓存和协商缓存。

  • private(默认值),所有的内容只有客户端才可以缓存,代理服务器不能缓存。

这些值可以混合使用,优先级如下:(网图,我翻译了一下)
在这里插入图片描述

其他一些注意点:

  • HTTP 1.1 之前,如果想使用 no-cache,通常设置 Pragma: no-cache(这也是 Pragma 字段唯一的取值)。但这个字段只是浏览器约定俗成的实现,缺乏可靠性,只是作为兼容字段出现。
  • HTTP 1.1 开始,Expires 逐渐被 Cache-control 取代。而为了兼容 HTTP 1.0HTTP 1.1 ,实际上这2个字段都会配置。

协商缓存

当强缓存超时失效后,就需要使用协商缓存,有服务器来决定缓存资源是否失效(也就是强缓存中的有效性判断。)

服务器资源为更新时,验证请求返回 304,大致流程如下图示:

而如果资源更新了,验证请求返回 200

特点:协商缓存并不会减少请求的数量。但如果是304,请求只会返回一个状态码,没有实际的资源内容,所以会减少响应体体积,来缩短网络传输时间。

协商缓存作为强缓存失效的后备解决方案,一般会和强缓存一起使用。通过2组字段来实现:

  • Last-Modified & If-Modified-Since
  • Etag & If-None-Match
Last-Modified & If-Modified-Since

Last-Modified 是响应头,If-Modified-Since 是请求头。

  1. 首先,服务器通过 Last-Modified 字段告知浏览器,资源最后一次被修改的时间。
Last-Modified: Thu, 21 Dec 2023 00:28:00 GMT
  1. 浏览器将资源和这个字段的值保留在缓存中。
  2. 再次请求相同资源时,浏览器从自己的缓存中找出 “不确定是否过期的” 缓存(也就是强缓存失效,已经命中协商缓存了)。并在请求头的 If-Modified-Since 字段中写入保存的 Last-Modified 的值。
  3. 服务器会将接收到的 If-Modified-Since 的值与服务端的 Last-Modified 字段进行对比。相等则表示未修改,响应 304;反之,则表示修改了,响应 200 状态码,并返回数据。

缺点:因为它的时间单位是秒,所以如果资源的更新速度是秒以下的单位,则无法使用该缓存。

Etag & If-None-Match

为了解决上面的问题,所以在出现了这组新的字段。

ETag 是响应头,If-None-Match 是请求头。

ETag 是资源的标识符,一般为一个 hash 值,在服务器存储。

整体流程和 Last-Modified & If-Modified-Since 类似,只是做了替换 Last-Modified --> ETagIf-Modified-Since --> If-None-Match

流程如下图示:


二者对比:

  • 精度:Etag > Last-Modified,因为 Etag 是一个 hash 值,每次都会改变从而确保精度。
  • 性能:Last-Modified > Etag,因为 Etag 需要服务器通过算法来计算 Hash 值。而 Last-Modified 只需要记录时间。
  • 优先级:服务器校验优先考虑 Etag。

Disk Cache 整体流程图:

2,缓存读取规则

当浏览器要请求资源时:

  1. Service Worker 中获取内容(如果设置了 Service Worker)。

  2. 查看 Memory Cache

  3. 查看 Disk Cache。细分为:

    • 如果有强制缓存且未失效,则使用强制缓存,不请求服务器。这时的状态码全都是 200。

    • 如果有强制缓存但已失效,使用协商缓存,比较后确定 304 还是 200。

  4. 发送网络请求,等待网络响应。

  5. 把响应内容存入 Disk Cache(如果 HTTP 响应头信息有相应配置的话)。

  6. 把响应内容的引用存入 Memory Cache(无视 HTTP 头信息的配置)。

  7. 把响应内容存入 Service WorkerCache Storage(如果设置了 Service Worker)。

3,浏览器的一些行为

用户对浏览器的不同操作,会触发不同的缓存读取策略。

常见的有3种:

  1. 在地址栏输入地址访问时,浏览器会查找 Disk Cache 中是否有匹配。有则使用,没有发送则发送网络请求。
  2. 普通刷新(F5),因为标签页没有关闭,所以 Memory Cache 是可用的,会优先使用它。其次才是 Disk Cache
  3. 强制刷新(Ctrl / Shift + F5),浏览器不使用缓存,因此在 请求头 Request Headers 中会自动添加 Cache-Control: no-cache(为了兼容还会有Pragma: no-cache),服务器直接返回200和最新内容。

4,缓存最佳实践

频繁变动的资源

Cache-Control: no-cache

或(二者等效)

Cache-Control: max-age=0, must-revalidate

表示浏览器可以缓存资源,但每次使用缓存资源前都必须重新验证其有效性(通过 ETag 或者 Last-Modified)。

这样虽然每次都会发起 HTTP 请求,但当缓存内容仍然有效时可以跳过 HTTP 响应体的下载,来减少响应数据的大小。

不常变化的资源

Cache-Control: max-age=31536000

这类资源,可以设置一个很大的有效时间 31536000(一年)。这样浏览器之后请求相同 url 时会命中强制缓存。

由此带来的更新问题,可以在文件名后添加 hash,版本号等字符,从而达到更改资源 url 的目的。

注意之前的强制缓存并未失效,只是不再使用了而已。


以上。

service-worker-cache 参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1325383.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【优化】XXLJOB修改为使用虚拟线程

【优化】XXLJOB修改为使用虚拟线程 新建这几个目录 类&#xff0c; 去找项目对应的xxljob的源码 主要是将 new Thread 改为 虚拟线程 Thread.ofVirtual().name("VT").unstarted 以下代码是 xxljob 2.3.0版本 举一反三 去修改对应版本的代码 <!-- 定…

UG螺旋线命令的使用

螺旋线按照螺距类型可以分为两种类型&#xff1a; 1、等螺距螺旋线 2、变螺距螺旋线 等螺距螺旋线 变螺距螺旋线 沿矢量螺旋线 沿矢量螺旋线-线性大小和螺距 沿矢量螺旋线-沿脊线的线性 沿矢量螺旋线-沿脊线的线性 当我们想模拟弹簧被拉伸或压缩状态时&#xff0c;可以使用…

Python-基于fastapi实现SSE流式返回(类似GPT)

最近在做大模型对话相关功能&#xff0c;需要将对话内容流式返回给前端页面&#xff08;类似GPT的效果&#xff09;。下面直接说下如何实现&#xff1a; 1.首先导入fastapi和sse流式返回所需要的包 from fastapi import APIRouter, Response, status from sse_starlette.sse …

智能化运输与航空航天:发展历程、问题与未来趋势

导言 智能化运输与航空航天是当前科技领域的研究热点之一&#xff0c;本文将深入研究这一领域的发展历程、遇到的问题、解决过程&#xff0c;以及未来的可用范围。同时&#xff0c;我们将探讨各国在这一领域的应用情况和未来的研究趋势&#xff0c;分析在哪些方面能够取胜&…

Java操作Word修订功能:启用、接受、拒绝、获取修订

Word的修订功能是一种在文档中进行编辑和审阅的功能。它允许多个用户对同一文档进行修改并跟踪这些修改&#xff0c;以便进行审查和接受或拒绝修改。修订功能通常用于团队合作、专业编辑和文件审查等场景。 本文将从以下几个方面介绍如何使用免费工具Free Spire.Doc for Java在…

数据挖掘体系介绍

数据挖掘是什么&#xff1f; 简而言之&#xff0c;对数据进行挖掘&#xff0c;从中提取出有效的信息。一般我们会把这种信息通过概念、规则、规律、模式等有组织的方式展示出来&#xff0c;形成所谓的知识。特别是在这个大数据时代&#xff0c;当数据多到一定程度&#xff0c;…

shell 数组的详细用法

简介 数组是一种数据结构&#xff0c;用于存储和处理一组相关的数据元素。数组可以包含多个值&#xff0c;每个值都有一个索引&#xff0c;用于标识和访问它们。 目录 1. 数组的基本用法 1.1. 定义数组的方式 1.1.1. 直接赋值 1.1.2. declare声明数组 1.1.3. 索引赋值 1.…

山景DU561—32位高性能音频处理器(DSP)芯片

音频处理可以更好地捕捉和处理声音和音乐&#xff1b;而DSP音频处理芯片是一种利用数字信号处理技术进行音频处理的专用芯片&#xff1b;可用于多种应用&#xff0c;从音乐拾音到复杂的音频信号处理&#xff0c;和声音增强。 由工采网代理的山景DU561是一款集成多种音效算法高…

YOLOv5改进 | 卷积篇 | 通过RFAConv重塑空间注意力(深度学习的前沿突破)

一、本文介绍 本文给大家带来的改进机制是RFAConv&#xff0c;全称为Receptive-Field Attention Convolution&#xff0c;是一种全新的空间注意力机制。与传统的空间注意力方法相比&#xff0c;RFAConv能够更有效地处理图像中的细节和复杂模式(适用于所有的检测对象都有一定的…

CentOS安装Python解释,CentOS设置python虚拟环境,linux设置python虚拟环境

一、安装python解释器 1、创建解释器安装的目录&#xff1a;/usr/local/python39 cd /usr/local mkdir python39 2、下载依赖 yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make libffi-devel xz-devel …

MyBatis——MyBatis的ORM映射和MyBatis的配置文件升级

1.MyBatis的ORM映射 拷贝之前的工程&#xff1a; 1.1.什么是ORM映射 MyBatis只能自动维护库表”列名“与”属性名“相同时的对应关系&#xff0c;二者不同时无法自动ORM&#xff0c;如下&#xff1a; 1.2.列的别名 在SQL中使用 as 为查询字段添加列别名&#xff0c;以匹配…

Gin之GORM事务(转账操作)

禁用默认事务的操作 为了确保数据一致性,GORM 会在事务里执行写入操作(创建、更新、删除)。如果没有这方面的要求,您可以在初始化时禁用它,这将获得大约 30%+ 性能提升。 // 全局禁用 db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{SkipDef…

CCF编程能力等级认证GESP—C++6级—20230923

CCF编程能力等级认证GESP—C6级—20230923 单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09;判断题&#xff08;每题 2 分&#xff0c;共 20 分&#xff09;编程题 (每题 25 分&#xff0c;共 50 分)小杨买饮料小杨的握手问题 答案及解析单选题判断题编程题1编程题…

FAVDICE - Favorite Dice

题意&#xff1a;n个面的骰子&#xff0c;问期望骰多少次可以将所有n个面都骰到 思路&#xff1a;期望dp 状态表示&#xff1a;dp[i]代表已经骰出了i个面&#xff0c;还需要期望骰dp[i]次才能将n个面都骰到 状态转移&#xff1a;对于dp[i]我们考虑两种情况&#xff1a; 1、…

python flask+vue实现前后端图片上传

python flaskvue实现前后端图片上传 vue代码如下&#xff1a; <template><div><input type"file" change"handleFileChange"/><button click"uploadFile">上传</button><br><img :src"imageUrl&…

使用python免费调用Google发布的Gemini双子座大模型API

上期文章,我们介绍了google发布的Gemini双子座大模型,现在google开放了gemini-pro与gemini-pro- vision2个版本的API接口。 其中gemini-pro模型类似与ChatGPT,是一个文本输入输出聊天模型,而vision模型,顾名思义是一个多模态模型,可以支持图片与文本的输入。 我们进入如…

指定每个子字符串长度L将字符串S分割为多个长度最长为L的子字符串textwrap.wrap(s,L)

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 指定每个子字符串长度L 将字符串S分割为多个 长度最长为L的子字符串 textwrap.wrap(s,L) [太阳]选择题 请问以下代码最后输出的结果是&#xff1f; import textwrap a "You are…

OpenCV-9颜色空间的转换

颜色转换API&#xff1a;cvtColor&#xff08;img&#xff0c;colorsapce&#xff09; cvt含义为转换 convesion(转换) 下面为示例代码&#xff1a; import cv2# callback中至少有一个参数 def callback(value):passcv2.namedWindow("color", cv2.WINDOW_NORMAL) …

Python - 深夜数据结构与算法之 Map Set

目录 一.引言 二.Map 与 Set 1.Hash Table 2.Hash Function 3.Hash Collisions 4.Java/Python Code 三.经典算法实战 1.Two-Sum [1] 2.Group-Anagrams [49] 3.Valid-Anagram [242] 四.总结 一.引言 前面介绍了列表 List 及其衍生的栈 Stack 与队列 Queue&#xff0…