当前位置: 首页 > article >正文

[浏览器]缓存策略机制详解

在做页面性能优化的时候,有一个点容易被忽略,那就是资源缓存优化。
浏览器里缓存策略分为强缓存协商缓存以及不缓存,每个缓存策略都有其适用的优化场景。
下面为大家详解何为强缓存,协商缓存

先说结论强缓>协商>不缓存。

强缓存

顾名思义,强制缓存,也就是说我的资源请求一次之后,接下来的时间段里如果请求头命中了则直接返回缓存里的资源。通常我们可以在devtools network里看到诸如:
在这里插入图片描述

from (disk or memory) cache这样的描述时,这个资源就是走的强缓存,我们可以查看请求头里的字段
在这里插入图片描述
这里有两个属性要注意,一个是Expires,还有一个是Cache-Control

Expires

expires是http1.0的标准,意思在这个时间段里资源都是有效的,超过这个时间则过期需要重新请求。所以我们在请求时如果命中了expires则不会发起请求而是直接返回缓存(内存或者磁盘,对应的Memory,Disk)里的资源,没有命中则重新发起请求。
它是一个绝对值,所以我们可以修改本地的时间来让资源一直缓存或者直接失效。
正是因为这个不安全的因素,http1.0之后新增了Cache-Control字段来作为命中缓存的依据。

Cache Control

与expires不同 cache-control返回的是一个相对值,相对于资源缓存到服务器的时间。在这个有效期内则不会发起请求而是直接返回缓存,超出同样是发起请求来重新获取资源。


需要注意的是强缓存返回的状态码始终都是200,这点我们可以通过查看network里的大小这一栏来判断是否是强缓存,进而通过请求头来判断当前的缓存策略。
同时,上面我说的结论强缓大于协商的原因是,一旦走了强缓就不会再发起请求,所以自然而然就不会再命中协商缓存了。

协商缓存

同样从名字里我们可以知道,协商协商,肯定是客户端与服务器协商后决定究竟是走缓存呐还是重新发起请求。
协商缓存命中的判断依据是:

  • 首次请求:
    • 会在请求头上带上Last-Modified或者是ETag
  • 第二次请求时:
    • 判断请求头里的if-modified-since是否与Last-Modified相同或者是if-none-match === ETag,一旦有一个条件能达成则直接走缓存,否则就重新发起请求。

协商缓存会先在服务器里判断究竟是要走缓存还是重新发起请求,命中了协商缓存一般请求的状态码是304
在这里插入图片描述
点开请求头我们可以看到if-modified-sinceif-none-match
在这里插入图片描述
通过对比上一次发起的协商请求发现他们是一样的,这样就会命中协商缓存策略。

不缓存

就是不缓存资源,每次请求都拿最新的。
好处是不会被缓存资源困住,坏处是不缓存了每次都请求很耗服务器的性能。



下面通过koa来实现这3个不同的缓存策略机制,新建项目直接npm init -y,然后安装Koa和Koa router

import Koa from 'koa';
import Router from 'koa-router';
import fs from 'node:fs';
import path, { dirname } from 'node:path';
import { fileURLToPath } from 'node:url'const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const app = new Koa();
const filePath = path.join(__dirname, 'example.txt');
const router = new Router();router.get('/strong-cache', async ctx => {const stats = fs.statSync(filePath);const fileContent = fs.readFileSync(filePath, 'utf-8');// 缓存60sctx.set('Cache-Control', 'public, max-age=60');ctx.set('Expires', new Date(Date.now() + 60 * 1000).toUTCString());ctx.type = 'text/plain';ctx.body = fileContent
})router.get('/negotiation-cache', async ctx => {const stats = fs.statSync(filePath);const fileContent = fs.readFileSync(filePath, 'utf-8');const lastModified = stats.mtime.toUTCString();const etag = `"${stats.size}-${Date.parse(stats.mtime)}"`;ctx.set('Cache-Control', 'no-cache');ctx.set('Last-Modified', lastModified);ctx.set('ETag', etag);const ifModifiedSince = ctx.headers['if-modified-since'];const ifNoneMatch = ctx.headers['if-none-match']if ((ifModifiedSince === lastModified) || (ifNoneMatch === etag)) {ctx.status = 304;return;}ctx.type = 'text/plain';ctx.body = fileContent;
})router.get('/no-cache', async ctx => {const fileContent = fs.readFileSync(filePath, 'utf-8');ctx.set('Cache-control', 'no-store');ctx.set('Pragma', 'no-store');ctx.type = 'text/plain';ctx.body = fileContent;
})app.use(router.allowedMethods()).use(router.routes());app.listen(2000, () => {console.log('service run on http://localhost:2000')
})

运行这个服务,打开浏览器 然后在开发者工具devtools里的console里发起fetch请求测试

fetch('/strong-cache').then(res => res.text()).then(res => console.log(res))fetch('/negotiation-cache').then(res => res.text()).then(res => console.log(res))

然后再观察Network请求的情况即可。

http://www.lryc.cn/news/2387157.html

相关文章:

  • Vue修饰符全解析
  • OpenCV CUDA 模块图像过滤-----创建一个计算图像导数的滤波器函数createDerivFilter()
  • 计算机视觉与深度学习 | Python实现CEEMDAN-ABC-VMD-DBO-CNN-LSTM时间序列预测(完整源码和数据)
  • AWS関連職種向け:日本語面接QA集
  • 【Macos】安装前端环境rust+node环境
  • (01)华为GaussDB((基于PostgreSQL))高斯数据库使用记录,dbeaver客户端配置高斯驱动,连接高斯数据库
  • ARM Linux远程调试
  • day24Node-node的Web框架Express
  • Webpack和Vite构建工具有什么区别?各自的优缺点是什么
  • 让MySQL更快:EXPLAIN语句详尽解析
  • 基于谷歌浏览器的Web Crypto API生成一对2048位的RSA密钥(公钥+私钥),并以JSON格式(JWK)打印到浏览器控制台
  • [CSS3]rem移动适配
  • 向量数据库及ChromaDB的使用
  • CodeBuddy实现pdf批量加密
  • 编程中优秀大模型推荐:特点与应用场景深度分析
  • orm详解--查询执行
  • 运行打印Hello World启动了多少线程?
  • C++项目中调用C#DLL的的方式
  • 咳嗽止咳药笔记250526 , 磷酸苯丙哌林 , 喷托维林 , 右美沙芬
  • vue pinia 独立维护,仓库统一导出
  • 网络的协议和标准
  • 十六进制字符转十进制算法
  • 跟Gemini学做PPT:汇报背景图寻找指南
  • java交易所,多语言,外汇,黄金,区块链,dapp类型的,支持授权,划转,挖矿(源码下载)
  • (已开源-CVPR2024) RadarDistill---NuScenes数据集Radar检测第一名
  • 【MySQL】 数据库基础数据类型
  • 中小企业AI算力如何选?【显卡租赁】VS【自建服务器】
  • OpenHarmony 4.1版本应用升级到5.0版本问题记录及解决方案
  • std::initialzer_list 与花括号{}数据列表
  • 萤石云实际视频实时接入(生产环境)