HTTP缓存(Cache-Control、Expires 、ETag)
HTTP缓存
HTTP缓存( ETag、Cache-Control)——谷歌开发者 HTTP缓存有利于web性能优化
Cache-Control
例子
假设我们首页有一个请求,请求js文件
<script src="./main.js"></script>
如何让CSS和JS请求速度加快?
此时打开首页
发现这个文件大小为279KB,使用时间为382ms
如果再次刷新首页,那么这个文件还会被再次请求一次。那么如何重复利用之前获取的资源而不用反复请求呢?答案是HTTP缓存,这是性能优化的一个重要方面。
接下来在响应里设置响应头
Cache-Control: max-age=30
刷新两次首页
第二次的时间为0
响应头中的Cache-Control: max-age=30
表示客户端将这个缓存最多 保存30 秒,30秒后再次请求文件将会再次下载。
即: 设置这个响应头之后,浏览器请求时发现是相同的URL,浏览器直接从内存里返回已经缓存的main.js,没有向服务器发出请求
问题
- 为什么首页不设置Cache-Control呢? 如果首页缓存,刷新首页的时候根本不会请求服务器,那么如果服务器更新了代码,浏览器将没有办法接收到新的版本。一般首页,HTML不要设置Cache-Control。js和css要设置久一点例如10年,即一直保留有缓存。
- 那么js和css更新了怎么办?
浏览器请求时发现是相同的URL才使用缓存,那么可以设置查询参数,例如第二个版本的js可以写
<script src="./main.js?v=2"></script>
,来保证URL的不同,重新获取新的js文件。这样即可以缓存很久,又可以随时更新
例如知乎的网页里的请求:
总结
通过网络获取内容既速度缓慢又开销巨大。较大的响应需要在客户端与服务器之间进行多次往返通信,这会延迟浏览器获得和处理内容的时间,还会增加访问者的流量费用。因此,缓存并重复利用之前获取的资源的能力成为性能优化的一个关键方面。好在每个浏览器都自带了 HTTP 缓存实现功能。您只需要确保每个服务器响应都提供正确的 HTTP 标头指令,以指示浏览器何时可以缓存响应以及可以缓存多久。
Expires
- Expires 是以前用来控制缓存的http头,Cache-Control是新版的API。
- 现在首选 Cache-Control。
- 如果在Cache-Control响应头设置了 "max-age" 或者 "s-max-age" 指令,那么 Expires 头会被忽略。
- 响应头设置方式:
Expires: Wed, 21 Oct 2015 07:28:00 GMT
- Expires 响应头包含日期/时间, 即在此时候之后,响应过期。
注意: 因为过期标准的时间用的是本地时间,所以不靠谱,所以要游侠使用Cache-Control代替Expires
区别
- Cache-Control设置时间长度
- Expires 设置时间点
MD5
MD5是消息摘要算法。用于确保信息传输完整一致。
具体作用这样
接受一个String 或 Buffer,返回一个固定的String
如果接受的String改变,那么返回的String也会改变 例如将1.txt中的其中一个1改为0,那么返回值如下
可见返回至完全改变了 这个特性可以用来判断两次信息传输是否完整一致
ETag
例子:
例如我们请求一个js文件。 设置一个ETag响应头
设置的ETage响应头为这个JS文件的MD5值 查看响应:
那么:下一次请求这个JS的时候,浏览器会把上一次响应的那个ETage的值放到If-None-Match里面,如图:
这样做的作用是:如果请求和响应的MD5一样,说明不需要重新下载这个js文件。这时我们修改代码:
如果MD5一样,说明文件没改过,那么返回304
304 Not Modified: HTTP 304 未改变说明无需再次传输请求的内容,也就是说可以使用缓存的内容。
HTTP 304 没有响应体,因为不需要下载响应内容,直接用缓存就行了
ETag与 Cache-Control的区别
假设我们请求两个文件,CSS文件使用Cache-Control缓存,js文件使用ETag。 代码如下:
两个请求区别:
所以:
- 由于CSS的请求是用缓存(Cache-Control)的,所以直接不发请求
- 而js用的ETag,有请求也有响应,只不过如果MD5一样,那么就不下载响应体
- 【Python环境】《Python数据科学入门》试译 第一章 简介
- HLS Lesson20-实例分析
- WannaCry勒索病毒详细解读
- matlab GUI基础3
- 不使用反射的实体类方案
- matlab GUI基础1
- Why to do,What to do,Where to do 与 Lambda表达式!
- Cloak ; Dagger攻击:一种可针对所有版本Android的攻击技术(含演示视频)
- 实例探究字符编码:unicode,utf-8,default,gb2312 的区别
- 分布式计算,WCF+JSON+实体对象与WebService+DataSet效率大比拼
- 【自然框架】 页面里的父类—— 改进和想法、解释
- 线性神经网络
- 【数据可视化】深度解析大数据可视化设计案例分析
- 使用IE6看老赵的博客——比较完美版(可以在线查看、回复)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- API接口设计规范
- 陶瓷PCB电路板到底好在哪?
- Mysql常用函数——告别复杂sql
- Spring Boot读取配置文件的几种方式
- python菜鸟教程 | if else 判断
- Java 语言中十大“坑爹”功能!
- R语言生存分析可视化分析
- 全平台轻量开源verilog仿真工具iverilog+GTKWave使用教程
- R语言时间序列和ARIMA模型预测拖拉机销售的制造案例研究
- Windows10下安装linux子系统学习笔记
- 项目实践 | 从零开始学习Deep SORT+YOLO V3进行多目标跟踪(附注释项目代码)
- [OHIF-Viewers]医疗数字阅片-医学影像-Module: Panel-自定义面板-中-es6-Object.defineProperty()定义属性
- (数据科学学习手札90)Python+Kepler.gl轻松制作时间轮播地图
- WEB前端安全自查和加固
- 硬核!IDEA 中使用 Git 完整入门教程!