夜猫子的知识栈 夜猫子的知识栈
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

夜猫子

前端练习生
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • JavaScript文章

    • 33个非常实用的JavaScript一行代码
    • new命令原理
    • ES5面向对象
    • ES6面向对象
    • 多种数组去重性能对比
    • 获取ip地址
    • ES6扩展符运用
    • file、base64和blob互相转化
    • 图片转base64格式
    • 实现异步队列
    • websocket实现二维码扫描
    • js动画之requestAnimationFrame
    • JS随机打乱数组
    • 判断是否为移动端浏览器
    • 将一维数组按指定长度转为二维数组
    • 防抖与节流函数
    • 时间戳与倒计时
    • JS获取和修改url参数
    • 比typeof运算符更准确的类型判断
    • 前端下载excel文件
    • 商品sku算法
    • 数组与对象的互相转化
    • Javascript原生事件监听及手动触发
    • JS编码与转码
    • 树结构与扁平化相互转换
    • 实现微信登录
    • 判断两个对象值是否相等
    • 常用表单验证
    • 在H5中实现OCR拍照识别身份证功能
    • 滚动条元素定位
    • 获取目标容器内的元素列表
    • 微信H5支付
    • 对象除空
    • 获取指定链接的参数
    • js中的函数注释
    • 大模型流式数据前端实现
    • 定高虚拟列表
    • 不定高虚拟列表
    • 虚拟表格
    • 移动端文件预览
    • 浏览器缓存机制
      • 一、什么是浏览器缓存?
      • 二、为什么使用缓存?
      • 三、浏览器的缓存规则
      • 四、如何控制缓存?
      • 五、不能缓存的请求
    • 前端从剪切板获取word图片
  • 前端架构

  • 学习笔记

  • 全栈项目

  • 前端
  • JavaScript文章
夜猫子
2024-08-23
目录

浏览器缓存机制

# 浏览器缓存机制

浏览器缓存对于前端一点都不陌生,最常见的就是,新版本上线了,测试却说这怎么还没有变化呢?使用 ctr + F5 强制刷新之后,立马就好了。或者清除浏览器缓存,按住ctr+shift+delete,弹出如图:

前端性能优化(二)——浏览器缓存机制

我们会发现目前浏览器缓存的图片和文件的大小。或者进入chrome://chrome-urls/找到chrome://cache/ 就可以看到所有缓存的地址列表。对于浏览器缓存,前端对它是又爱又恨,有时想保留,有时想禁掉,所以看看浏览器缓存到底是怎样的?

# 一、什么是浏览器缓存?

浏览器缓存就是浏览器根据 url 第一次访问网站之后,将网站的 html、css、js、图片等文件复制一份保留到浏览器中,当你二次访问这个 url 的网站时,如果网站没有明确表示有更新时,浏览器直接在缓存中查找内容,不会再次请求网页内容,只有网页明确表示有更新时,浏览器才会向服务器发起网路请求,再次下载网页。

前端性能优化(二)——浏览器缓存机制

如上图,百度首页就是使用了缓存机制,首次访问之后 web资源被缓存,在后面重复请求中,资源直接在缓存中读取,而不是向服务器请求资源。

# 二、为什么使用缓存?

2.1、为什么很多网站二次打开速度很快?

网页二次打开很快,主要原因是第一次加载页面过程中,缓存了部分耗时数据,这一现象,对于单页面应用开发非常明显。

上一篇文章《浏览器工作原理》中,浏览器工作流程介绍,输入网址回车以后浏览器向服务器发起服务之前,会现在浏览器缓存中查询是否有需要的文件?如果有则直接在缓存中获取文件,避免向服务器请求和下载文件,所以节省了一部分时间。

2.2、浏览器缓存优点

1、减少网络带宽消耗

对于网站运营者或者访问网页的用户,带宽就代表着 money ,过多的消耗带宽,我们服务器配置就得升级,使用浏览器缓存之后,就会减少网络流量,降低运营成本。

2、降低服务器压力

使用浏览器缓存之后,除第一次访问需要向服务器请求网站全部资源,后续访问可以重复使用浏览器本地缓存,减少对服务器的请求,间接降低服务器的压力,同时,搜索引擎的爬虫也会根据缓存过期机制降低抓取的频率,也可以降低服务器压力。

3、减少网络延迟,加快网页加载

浏览器缓存 web资源后,减少网络请求,可以更快速地获取到服务器返回数据,同时使用浏览器缓存内的文件比服务器获取快很多,所以网页加载速度明显快很多。

# 三、浏览器的缓存规则

浏览器的缓存判断分为强缓存和协商缓存两种。

强缓存

浏览器在加载资源时,会先根据本地缓存资源的 header 中的信息判断是否命中强缓存,如果命中则直接使用缓存中的资源不会再向服务器发送请求。

这里的 header 中的信息指的是 expires 和 cahe-control.

协商缓存

当强缓存没有命中的时候,浏览器会发送一个请求到服务器,服务器根据 header 中的部分信息来判断是否命中缓存。如果命中,则返回 304 ,告诉浏览器资源未更新,可使用本地的缓存。

这里的 header 中的信息指的是 Last-Modify/If-Modify-Since 和 ETag/If-None-Match.

对于浏览器端的缓存来讲,这些规则是在 http 协议和 meta 标签中定义的。分别从两个维度:新鲜度和校验值,规定浏览器是否可以直接使用缓存中的副本,还是直接从服务器获取最新资源。

3.1、新鲜度(过期):浏览器缓存的有效期,缓存必须满足以下两个条件,浏览器才会认为是最新的,可以直接使用。

  • 含有完整的过期时间控制头信息,并在有效期内。
  • 浏览器已经使用过这个副本,并且在会话中已经检查过新鲜度。

3.2、校验值(验证):服务器返回资源的时候,会在响应头信息中带上资源实体标签 Entity Tag,可以用来作为浏览器再次请求过程的校验标识,如果发现校验标识不匹配,说明资源已经被修改过或过期,浏览器需要重新请求资源。

当浏览器再次访问一个已经访问过的资源时,它会这样做:

1.看看是否命中强缓存,如果命中,就直接使用缓存了。

2.如果没有命中强缓存,就发请求到服务器检查是否命中协商缓存。

3.如果命中协商缓存,服务器会返回 304 告诉浏览器使用本地缓存。

4.否则,返回最新的资源

# 四、如何控制缓存?

缓存规则可以设置在html的meta标签,也可以设置在http协议头内。

4.1、前端 html 中 meta 标签

在 html 页面中加入缓存设置,代码如下:

<meta http-equiv="Pragma" content="no-cache"  />
<!-- Pragma是http1.0版本中给客户端设定缓存方式之一 -->
1
2

上边代码,禁止浏览器缓存,浏览器每次访问网页都要去服务器请求。事实这种禁用缓存形式作用有限:

  • 只有IE浏览器才能标识这段 meta 的含义,其他主流浏览器仅认识 “Cache-Control:no-store” 的 meta 标签。
  • 在IE浏览器中,并不一定添加 pragma,但是会让当前网页每次都会向服务器发送请求。

4.2、HTTP协议头

http请求和响应头中,与缓存相关的常见类型:

规则 消息报头 值/示例 类型 作用
新鲜度 Pragma no-cache 响应 告诉浏览器忽略资源的缓存副本,每次访问都需要去服务器拉取【http1.0中存在的字段,在http1.1已被抛弃,使用Cache-Control替代,但为了做http协议的向下兼容,很多网站依旧会带上这个字段】
Expires Mon, 15 Aug 2016 03:56:47 GMT 响应 启用缓存和定义缓存时间。告诉浏览器资源缓存过期时间,如果还没过该时间点则不发请求【http1.0中存在的字段,该字段所定义的缓存时间是相对服务器上的时间而言的,如果客户端上的时间跟服务器上的时间不一致(特别是用户修改了自己电脑的系统时间),那缓存时间可能就没啥意义了。在HTTP 1.1版开始,使用Cache-Control: max-age=秒替代】
Cache-Control no-cache 响应 告诉浏览器忽略资源的缓存副本,强制每次请求直接发送给服务器,拉取资源,但不是“不缓存”
no-store 响应 强制缓存在任何情况下都不要保留任何副本
max-age=[秒] 响应 指明缓存副本的有效时长,从请求时间开始到过期时间之间的秒数
public 响应 任何路径的缓存者(本地缓存、代理服务器),可以无条件的缓存该资源
private 响应 只针对单个用户或者实体(不同用户、窗口)缓存资源
Last-Modified Mon, 15 Aug 2016 03:56:47 GMT 响应 告诉浏览器这个资源最后的修改时间。服务器将资源传递给客户端时,会将资源最后更改的时间以“Last-Modified: GMT”的形式加在实体首部上一起返回给客户端【只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间】
If-Modified-Since Mon, 15 Aug 2016 03:56:47 GMT 请求 其值为上次响应头的Last-Modified值,再次向web服务器请求时带上头If-Modified-Since。web服务器收到请求后发现有头If-Modified-Since则与被请求资源的最后修改时间进行比对。若最后修改时间较新,说明资源又被改动过,则响应整片资源内容(写在响应消息包体内),包括更新Last-Modified的值,HTTP 200;若最后修改时间较旧,说明资源无新修改,则响应HTTP 304(无需请求,节省浏览),告知浏览器继续使用所保存的cache
校验值 ETag "fd56273325a2114818df4f29a628226d" 响应 告诉浏览器当前资源在服务器的唯一标识符(生成规则由服务器决定)
If-None-Match "fd56273325a2114818df4f29a628226d" 请求 当资源过期时(使用Cache-Control标识的max-age),发现资源具有Etage声明,则再次向web服务器请求时带上头If-None-Match(Etag的值)。web服务器收到请求后发现有头If-None-Match则与被请求资源的相应校验串进行比对,决定返回200或304

各种类型之间的关系和区别:

  • Cache-Control 与 Expires:它两作用一样,都表明当前资源的有效期,控制浏览器是取缓存还是直接向服务器获取,Cache-Control可以设置的更细致,如果同时设置,它的优先级高于Expires。
  • Last-Modified / ETag 与 Cache-Control / Expires:配置Last-Modified/ETag的情况下,浏览器再次访问URL的资源,还是会发送请求到服务器,询问文件是否已经修改,如果没有,服务器会给浏览器返回304,浏览器直接从本地缓存中取就好了,反之,服务器会直接向浏览器返回数据。Cache-Control / Expires 检测本地缓存是否还在有效期内,在有效期内,直接使用本地缓存,阻止发送请求。如果同时设置,Cache-Control / Expiress 优先级更高。一般情况下,两者配合使用,因为即使服务器设置缓存时间, 当用户点击“刷新”按钮时,浏览器会忽略缓存继续向服务器发送请求,这时Last-Modified/ETag将能够很好利用304,从而减少响应开销。
  • Last-Modified 与 ETag:ETag主要是为了解决Last-Modified比较难解决的问题:1、Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的新鲜度。2、如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存。3、有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形。ETag是服务器自动生成或开发者生成对应资源在服务器的唯一标识符,能够更加精准控制缓存。两者可以一起使用,服务器优先验证ETag,一致时,才会继续比对Last-Mofifed,才决定是否要返回304。

# 五、不能缓存的请求

并不是所有的请求都能被缓存,无法被缓存的有:

  • post 请求无法被缓存。
  • 需要根据cookie、认证信息等决定输入内容的动态请求不能被缓存。
  • http响应头中不包含Last-Modified/ETag,也不包含Cache-Control/Expiress的请求无法被缓存。
  • http信息头明确设置Cache-Control:no-cache,pragma:no-cache或Cache-Control:max-age=0浏览器不缓存时。
编辑 (opens new window)
上次更新: 2024/8/26 18:11:40
移动端文件预览
前端从剪切板获取word图片

← 移动端文件预览 前端从剪切板获取word图片→

最近更新
01
IoC 解决了什么痛点问题?
03-10
02
如何调试 Nest 项目
03-10
03
Provider注入对象
03-10
更多文章>
Copyright © 2019-2025 Study | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式