深入理解浏览器缓存机制 ( http )

2023-11-17

一、介绍
http缓存:浏览器根据当前http请求报文策略网路资源存储到本地内存(memory cache)/硬盘(disk cache)中

缓存流程:

浏览器 浏览器缓存 服务端 发起请求,根据缓存规则验证缓存 没有缓存或者缓存标识失效/过期,发起网络请求 请求完成,返回请求结果,缓存标识 缓存网络资源,缓存标识 浏览器 浏览器缓存 服务端

二、访问缓存优先级

  • 次访问资源时,先从内存中查找,如果内存中有,直接加载
  • 如果内存中没有,则从硬盘中查找,如果硬盘中有,直接加载
  • 如果硬盘中也没有,就会进行网络请求,成功后将网络资源存储到内存/硬盘中

三、分类

  • 强缓存
  • 协商缓存

优先进行强缓存,强缓存失效后,进行协商缓存

强缓存

不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的Network选项中可以看到该请求返回200的状态码,并且Size显示from disk cache或from memory cache。强缓存可以通过设置两种 HTTP Header 实现:Expires 和 Cache-Control

Expires: Sun, 26 Apr 2020 18:00:00 GMT 最大过期时间 2020/04/26 18:00:00

Expires:缓存过期时间,如果请求资源在到期时间内,直接从缓存里读取。因为是绝对时间,受限于本地时间,如果修改本地时间,可能会导致缓存失效

Cache-Control:max-age=300

Cache-Control:max-age=300 代表当前请求返回时间的5分钟之后,再次请求,直接从缓存里读取。默认值 private:

Cache-Control 指令有很多,并且可以组合使用:

指令 作用
public 所有内容都将被缓存(客户端和代理服务器都可缓存)
private 所有内容只有客户端可以缓存
no-cache 不使用强缓存,使用协商缓存
no-store 所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
max-age 表示缓存将在多少秒后失效
s-maxage 同max-age作用一样,只在代理服务器中生效,s-maxage的优先级高于max-age

接下来我们测试一下强缓存:

注意:
在这里插入图片描述

这里把勾去掉,否则不会使用缓存

serve.js

let express = require('express')
let app = express()
let fs = require('fs')
let router = express.Router() // 这里使用Router

// 设置全局响应头
router.all('*', (req, res, next) => {
  res.set({
    'Cache-Control':'max-age=300' // 5分钟缓存时间
  })
  next()
})

// 静态资源
router.use(express.static('dist')) // 里面有index.html / 图片等静态资源

router.get('/userList', (req, res) => {
  res.send({'name':'小明'})
})

app.use('/user',router) // 挂载

let server = app.listen(3000, '127.0.0.1', () => {
  let host = server.address().address
  let port = server.address().port

  console.log('Server running at http://' + host + ':' + port)
})

接下来我们访问 127.0.0.1:3000/user/index.html

可以看到 强缓存已生效
在这里插入图片描述
接下来,我们F5刷新页面,此时进程还在,并且在缓存时间内,根据浏览器缓存原理,应该从 memory cache 中读取图片

注意:这里切勿 ctrl + F5 强制不走缓存

我们可以看到 form memory cache 从内存中读取图片 !!!

接下来,我们把进程关掉,在缓存时间内,根据浏览器缓存原理,应该从 disk cache 硬盘中读取图片
在这里插入图片描述
看到 form disk cache 从硬盘中读取图片,完全符合访问缓存优先级

接下来,我们尝试 5 分钟之后,也就是请求缓存时间到期后,再次请求
在这里插入图片描述
我们可以看到,缓存时间到期后,直接从服务端发起请求

总结流程,在缓存时间内:

浏览器 内存 硬盘 服务端 发起请求,先在内存寻找 如果存在,内存直接返回 如果不存在,硬盘寻找 如果硬盘中存在缓存资源,硬盘直接返回 如果硬盘中不存在,则向服务端发起网络请求 请求完成,返回请求结果,浏览器缓存资源 浏览器 内存 硬盘 服务端

协商缓存

如果不设置 Cache-Control 默认public,max-age=0,当然我们可以设置为 Cache-Control : no-cache

serve.js

let express = require('express')
let app = express()
let fs = require('fs')
let router = express.Router() // 这里使用Router

// 设置全局响应头
router.all('*', (req, res, next) => {
  res.set({
    'Cache-Control':'no-cache' // 进行协商缓存
  })
  next()
})

// 静态资源
router.use(express.static('dist')) // 里面有index.html / 图片等静态资源

router.get('/userList', (req, res) => {
  res.send({'name':'小明'})
})

app.use('/user',router) // 挂载

let server = app.listen(3000, '127.0.0.1', () => {
  let host = server.address().address
  let port = server.address().port

  console.log('Server running at http://' + host + ':' + port)
})

接下来我们访问 127.0.0.1:3000/user/index.html

可以看到,Cache-Control : no-cache 已经生效
在这里插入图片描述
我们发现返回值多了ETag 和 Last-Modified

Etag

代表我们当前请求的数据在服务端的唯一标识,首次请求时,服务端会返回Etag标识,浏览器下次请求时,会带上赋值后的 If-None-Match 参数,并且与返回的ETag进行对比,如果一致则命中协商缓存。返回 304 Not Modified

Last-Modified

代表请求的数据在服务端最后一次修改的时间,同理,首次请求时,服务端会返回Last-Modified标识,浏览器下次请求时,会带上赋值后的 If-Modified-Since 参数,并且与返回的Last-Modified进行对比,如果一致则命中协商缓存。返回 304 Not Modified

!!!注意:Etag 的优先级要高于 Last-Modified,所以请求时,如果ETag存在,则对比 If-None-Match,反之对比 If-Modified-Since

接下来我们测试协商缓存:
在这里插入图片描述

可以看到,Etag 与 If-None-Match 对比一致,命中协商缓存,返回 304 Not Modified

然后,我们修改服务端静态资源,再次请求
在这里插入图片描述
我们会看到浏览器保留的 If-None-Match 与 响应头 Etag 对比不一致,缓存策略失效!!!发送请求

总结协商缓存:

浏览器 内存 服务端 发起请求,如果有ETag 对比Etag / If-None-Match 若一致,返回缓存数据 304 如果不存在ETag,寻找Last-Modified,对比Last-Modified / If-Modified-Since,若一致,返回缓存数据 304 如果都不存在,则向服务端发送请求 请求完成,返回请求结果,浏览器缓存资源/标识 F5 与 ctrl+F5 都会释放内存 浏览器 内存 服务端

至此,我们就彻底搞懂http缓存机制

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入理解浏览器缓存机制 ( http ) 的相关文章

随机推荐

  • 自动生成代码的配置generator.properties

    u4EE3 u7801 u751F u6210 u5668 uFF0C u914D u7F6E u4FE1 u606F u5305 u540D package com zscat cms u4F5C u8005 author zscat E
  • python使用scipy.optimize的fsolve求解线性(非线性)方程

    文章目录 求解线性方程 求解非线性方程 求解线性方程 对于固定的线性方程 a 2b 0 4a 5b 0 求 a 与 b 使用如下方法 import scipy optimize as opt import numpy as np def f
  • 【JDK版本常见报错及其解决,Java基础知识点百度云

    J2SE 8 52 J2SE 7 jdk1 7 51 J2SE 6 0 jdk1 6 50 J2SE 5 0 jdk1 5 49 JDK 1 4 48 JDK 1 3 47 JDK 1 2 46 JDK 1 1 45 那怎么办 好办 把项目
  • 【链表】环型链表找环的起点

    力扣 142 环型链表 II 题目 给定一个链表的头节点 head 返回链表开始入环的第一个节点 如果链表无环 则返回 null 1 先确定链表存在环 使用快慢指针法 分别定义 fast 和 slow 指针 从头结点出发 fast 指针每次
  • FFmpeg中的常见结构体

    代码基于FFmpeg5 0 1 目录 FFFormatContext AVFormatContext AVIOContext FFIOContext URLContext URLProtocol AVInputFormat FFStream
  • PAT甲级刷题:模拟(不断更新)

    目录 1001 A B Format 1005 Spell It Right 1035 Password 1061 Dating 18 20 1073 Scientific Notation 16 20 1077 Kuchiguse 17
  • Java 华为真题-猴子爬山

    需求 一天一只顽猴想去从山脚爬到山顶 途中经过一个有个N个台阶的阶梯 但是这猴子有一个习惯 每一次只能跳1步或跳3步 试问猴子通过这个阶梯有多少种不同的跳跃方式 输入描述 输入只有一个整数N 0
  • k8s中各组件和kube apiserver通信时的认证和鉴权

    背景 和master节点kube api server通信的组件有很多 包括 kubelet calico scheduler kubectl 某些pod可能会和kube api server通信 这些组件和api server通信时用的是
  • Springboot使用EasyExcel读写excel(详细)

    文章目录 使用EasyExcel读取Excel 一 关于EasyExcel 二 读取excel 实体类 本地读取 controller上传 创建监听器 三 导出excel 实体类 本地导出 Controller下载 使用EasyExcel读
  • 模糊pid控制的温度系统matlab源代码_模糊PID控制系统(一)模糊入门

    1 matlab模糊工具箱 1 1 matlab命令 fuzzy 打开fuzzy设计工具箱 1 2 添加输入输出 隶属度函数 数值范围 1 3 确定模糊规则表 添加模糊规则 也可在matlab 编辑器里编辑 fis文件 1 4 反模糊化 1
  • HTTP协议之multipart/form-data请求分析

    无意中发现了一个巨牛的人工智能教程 忍不住分享一下给大家 教程不仅是零基础 通俗易懂 而且非常风趣幽默 像看小说一样 觉得太牛了 所以分享给大家 点这里可以跳转到教程 首先来了解什么是multipart form data请求 根据http
  • hook-setInterval定时器

    目标网站 aHR0cDovL3NwaWRlci53YW5nbHVvemhlLmNvbS9jaGFsbGVuZ2UvNQ 背景 本题为hook初体验 目标是用hook的方式过掉定时器 成功在控制台中打印出我们想要的内容 表现形式 1 一进入页
  • 【Java愚公】Windows安装wsl2

    Windows安装wsl2 查看window有没有安装wsl 在window下安装wsl 查看window有没有安装wsl 在cmd命令面板输入 wsl 没有安装wsl输入会报错 在window下安装wsl 通过在管理员PowerShell
  • js实现图片上下滚动background-position

  • 关于js报错 Cannot read property innerHTML of null和关于Cannot set property ‘innerHTML’ of null 错误原因

    解决关于js报错 Cannot read property innerHTML of null 1 相信很多同学在开发过程中都会遇到 Cannot read property innerHTML of null 这个报错的字面含义是 不能读
  • 前端文件下载的八种方法(解决pdf、图片在浏览器自动打开问题)

    系列文章目录 现在流行的chrom 和火狐浏览器 都会将图片和文档自动打开 图片自动打开的问题已经解决 请看第三条 提示 下面代码中会用到a标签中 target 会添加一个 view window 的属性 如果想要详细了解a标签的属性 可以
  • rabbitMQ初识

    消息队列 RabbitMQ 认识MQ 同步和异步通讯 微服务间通讯有同步和异步两种方式 同步通讯 就像打电话 需要实时响应 异步通讯 就像发邮件 不需要马上回复 同步通讯 同步调用的优点 时效性较强 可以立即得到结果 同步调用的问题 耦合度
  • C++之多重继承

    大多数应用程序使用单个基类的公用继承 但是在某些情况下 单继承是不够的 必须使用多继承 C 允许为一个派生类指定多个基类 这样的继承结构被称做多重继承 举个例子 交通工具类可以派生出汽车和船连个子类 但拥有汽车和船共同特性水陆两用汽车就必须
  • 使用Android studio开发第一个小程序

    1 点击新建安卓项目 填入项目名称 公司域 项目的修饰 项目路径 若不存在 会新建一个路径 下面两个不要选 点击下一步 2 接下来就是项目配置了 在这里我们只勾选第一个 适配的手机系统最小sdk版本 目前经常用的是API 17 当然你也可以
  • 深入理解浏览器缓存机制 ( http )

    一 介绍 http缓存 浏览器根据当前http请求报文策略 将网路资源存储到本地内存 memory cache 硬盘 disk cache 中 缓存流程 浏览器 浏览器缓存 服务端 发起请求 根据缓存