前端学习笔记--HTTP缓存

原文地址:https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=zh-cn

缓存并重用之前获取的资源的能力是性能优化的一个关键方面。

每个浏览器都自带了 HTTP 缓存实现功能,只需要确保每个服务器响应都提供正确的 HTTP 标头指令,以指示浏览器何时可以缓存响应以及可以缓存多久。

 

HTTP 与浏览器交互的请求头:

HTTPCatch

当服务器返回响应时,还会发出一组 HTTP 标头,用于描述响应的内容类型、长度、缓存指令、验证令牌等。例如,在上图的交互中,服务器返回一个 1024 字节的响应,指示客户端将其缓存最多 120 秒,并提供一个验证令牌(“x234dff”),可在响应过期后用来检查资源是否被修改。

 

通过ETag验证缓存的响应

  • 服务器使用ETag HTTP表头传递验证令牌
  • 验证令牌可以实现高效率的资源检查:资源未发生变化时不会传送任何数据

验证令牌的作用:

假定在首次获取资源 120 秒后,浏览器又对该资源发起了新的请求。首先,浏览器会检查本地缓存并找到之前的响应。遗憾的是,该响应现已过期,浏览器无法使用。此时,浏览器可以直接发出新的请求并获取新的完整响应。不过,这样做效率较低,因为如果资源未发生变化,那么下载与缓存中已有的完全相同的信息就毫无道理可言!

这正是验证令牌(在 ETag 标头中指定)旨在解决的问题。服务器生成并返回的随机令牌通常是文件内容的哈希值或某个其他指纹。客户端不需要了解指纹是如何生成的,只需在下一次请求时将其发送至服务器。如果指纹仍然相同,则表示资源未发生变化,您就可以跳过下载。 例如:

在上例中,客户端自动在“If-None-Match” HTTP 请求标头内提供 ETag 令牌。服务器根据当前资源核对令牌。如果它未发生变化,服务器将返回“304 Not Modified”响应,告知浏览器缓存中的响应未发生变化,可以再延用 120 秒。请注意,您不必再次下载响应,这节约了时间和带宽。

作为网络开发者,如何利用高效的重新验证?浏览器会替我们完成所有工作:它会自动检测之前是否指定了验证令牌,它会将验证令牌追加到发出的请求上,并且它会根据从服务器接收的响应在必要时更新缓存时间戳。我们唯一要做的就是确保服务器提供必要的 ETag 令牌。检查服务器文档中有无必要的配置标志。

提示:HTML5 Boilerplate 项目包含所有最流行服务器的配置文件样例,其中为每个配置标志和设置都提供了详细的注解。在列表中找到您喜爱的服务器,查找合适的设置,然后复制/确认您的服务器配置了推荐的设置。

Cache-Control

  • 每个资源都可通过 Cache-Control HTTP 标头定义其缓存策略
  • Cache-Control 指令控制谁在什么条件下可以缓存响应以及可以缓存多久。

从性能优化的角度来说,最佳请求是无需与服务器通信的请求:可以通过响应的本地副本消除所有网络延迟,以及避免数据传送的流量费用。为实现此目的,HTTP 规范允许服务器返回 Cache-Control 指令,这些指令控制浏览器和其他中间缓存如何缓存各个响应以及缓存多久。

注:Cache-Control 标头是在 HTTP/1.1 规范中定义的,取代了之前用来定义响应缓存策略的标头(例如 Expires)。所有现代浏览器都支持 Cache-Control,因此,使用它就够了。

CacheControl

命令:

“no-cache”和“no-store”

“no-cache”表示必须先与服务器确认返回的响应是否发生了变化,然后才能使用该响应来满足后续对同一网址的请求。因此,如果存在合适的验证令牌 (ETag),no-cache 会发起往返通信来验证缓存的响应,但如果资源未发生变化,则可避免下载。

相比之下,“no-store”则要简单得多。它直接禁止浏览器以及所有中间缓存存储任何版本的返回响应,例如,包含个人隐私数据或银行业务数据的响应。每次用户请求该资产时,都会向服务器发送请求,并下载完整的响应。

“public”与“private”

如果响应被标记为“public”,则即使它有关联的 HTTP 身份验证,甚至响应状态代码通常无法缓存,也可以缓存响应。大多数情况下,“public”不是必需的,因为明确的缓存信息(例如“max-age”)已表示响应是可以缓存的。

相比之下,浏览器可以缓存“private”响应。不过,这些响应通常只为单个用户缓存,因此不允许任何中间缓存对其进行缓存。例如,用户的浏览器可以缓存包含用户私人信息的 HTML 网页,但 CDN 却不能缓存。

“max-age”

指令指定从请求的时间开始,允许获取的响应被重用的最长时间(单位:秒)。例如,“max-age=60”表示可在接下来的 60 秒缓存和重用响应。

定义最佳的Cache-Control 策略

CacheControl策略

按照以上决策树为您的应用使用的特定资源或一组资源确定最佳缓存策略。在理想的情况下,您的目标应该是在客户端上缓存尽可能多的响应,缓存尽可能长的时间,并且为每个响应提供验证令牌,以实现高效的重新验证。

Cache-Control 指令和说明
max-age=86400浏览器以及任何中间缓存均可将响应(如果是“public”响应)缓存长达 1 天(60 秒 x 60 分钟 x 24 小时)。
private, max-age=600客户端的浏览器只能将响应缓存最长 10 分钟(60 秒 x 10 分钟)。
no-store不允许缓存响应,每次请求都必须完整获取。

 

根据 HTTP Archive,在排名最高的 300,000 个网站(按照 Alexa 排名)中,所有下载的响应中几乎有半数可由浏览器缓存,这可以大量减少重复的网页浏览和访问。当然,这并不意味着您的特定应用有 50% 的资源可以缓存。一些网站的资源 90% 以上都可以缓存,而其他网站可能有许多私密或时效要求高的数据根本无法缓存。

审核网页,确定哪些资源可以缓存,并确保它们返回正确的 Cache-Control 和 ETag 标头。

废弃和更新缓存的响应

  • 在资源“过期”之前,将一直使用本地缓存的响应。
  • 您可以通过在网址中嵌入文件内容指纹,强制客户端更新到新版本的响应。
  • 为获得最佳性能,每个应用都需要定义自己的缓存层次结构。

浏览器发出的所有 HTTP 请求会首先路由到浏览器缓存,以确认是否缓存了可用于满足请求的有效响应。如果有匹配的响应,则从缓存中读取响应,这样就避免了网络延迟和传送产生的流量费用。

不过,如果想更新或废弃缓存的响应,该怎么办? 例如,假定已告诉访问者将某个 CSS 样式表缓存长达 24 小时 (max-age=86400),但设计人员刚刚提交了一个您希望所有用户都能使用的更新。该如何通知拥有现在“已过时”的 CSS 缓存副本的所有访问者更新其缓存?在不更改资源网址的情况下,做不到。

浏览器缓存响应后,缓存的版本将一直使用到过期(由 max-age 或 expires 决定),或一直使用到由于某种其他原因从缓存中删除,例如用户清除了浏览器缓存。因此,构建网页时,不同的用户可能最终使用的是文件的不同版本;刚获取了资源的用户将使用新版本的响应,而缓存了早期(但仍有效)副本的用户将使用旧版本的响应。

所以,如何才能鱼和熊掌兼得:客户端缓存和快速更新? 可以在资源内容发生变化时更改它的网址,强制用户下载新响应。通常情况下,可以通过在文件名中嵌入文件的指纹或版本号来实现 - 例如 style.x234dff.css。

更新缓存

因为能够定义每个资源的缓存策略,所以可以定义“缓存层次结构”,这样不但可以控制每个响应的缓存时间,还可以控制访问者看到新版本的速度。为了进行说明,我们一起分析一下上面的示例:

  • HTML 被标记为“no-cache”,这意味着浏览器在每次请求时都始终会重新验证文档,并在内容变化时获取最新版本。此外,在 HTML 标记内,在 CSS 和 JavaScript 资产的网址中嵌入指纹:如果这些文件的内容发生变化,网页的 HTML 也会随之改变,并会下载 HTML 响应的新副本。
  • 允许浏览器和中间缓存(例如 CDN)缓存 CSS,并将 CSS 设置为 1 年后到期。请注意,可以放心地使用 1 年的“远期过期”,因为在文件名中嵌入了文件的指纹:CSS 更新时网址也会随之变化。
  • JavaScript 同样设置为 1 年后到期,但标记为 private,这或许是因为它包含的某些用户私人数据是 CDN 不应缓存的。
  • 图像缓存时不包含版本或唯一指纹,并设置为 1 天后到期。

可以组合使用 ETag、Cache-Control 和唯一网址来实现一举多得:较长的过期时间、控制可以缓存响应的位置以及随需更新。

缓存检查清单

不存在什么最佳缓存策略。需要根据通信模式、提供的数据类型以及应用特定的数据更新要求,为每个资源定义和配置合适的设置,以及整体的“缓存层次结构”。

在制定缓存策略时,需要牢记下面这些技巧和方法:

  • 使用一致的网址:如果在不同的网址上提供相同的内容,将会多次获取和存储这些内容。提示:请注意,网址区分大小写。
  • 确保服务器提供验证令牌 (ETag):有了验证令牌,当服务器上的资源未发生变化时,就不需要传送相同的字节。
  • 确定中间缓存可以缓存哪些资源:对所有用户的响应完全相同的资源非常适合由 CDN 以及其他中间缓存进行缓存。
  • 为每个资源确定最佳缓存周期:不同的资源可能有不同的更新要求。为每个资源审核并确定合适的 max-age。
  • 确定最适合的网站的缓存层次结构:可以通过为 HTML 文档组合使用包含内容指纹的资源网址和短时间或 no-cache 周期,来控制客户端获取更新的速度。
  • 最大限度减少搅动:某些资源的更新比其他资源频繁。如果资源的特定部分(例如 JavaScript 函数或 CSS 样式集)会经常更新,可以考虑将其代码作为单独的文件提供。这样一来,每次获取更新时,其余内容(例如变化不是很频繁的内容库代码)可以从缓存获取,从而最大限度减少下载的内容大小。

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

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

相关文章

socket programming

进行 socket programming开始要做的工作&#xff1a; On Linux: 以下是client代码&#xff0c;使用TCP&#xff0c;注意网络字节序&#xff1a; 1 #include <sys/socket.h> 2 #include <netinet/in.h> 3 #include <arpa/inet.h> 4 int main() 5 { 6 …

如何用Veripacks替换构建模块

比较下面的两棵树。 在这两种情况下&#xff0c;目标都是拥有一个具有两个独立模块&#xff08; frontend和reporting &#xff09;和一个共享/公用模块&#xff08; domain &#xff09;的应用程序。 frontend的代码不应访问reporting代码&#xff0c;反之亦然。 两个模块都可…

JS的DOM和BOM

* JavaScript分三个部分: ECMAScript标准:JS的基本的语法DOM:Document Object Model --->文档对象模型----操作页面的元素BOM:Browser Object Model----->浏览器对象模型---操作的是浏览器一、DOM对象 文档:把一个html文件看成是一个文档,由于万物皆对象,所以把这个文档看…

mysql建表的规则_MYSQL建表规则 - Love彼岸花开的个人空间 - OSCHINA - 中文开源技术交流社区...

建立表规约【强制】表名、字段名必须使用小写字母或数字&#xff0c;禁止出现数字开头&#xff0c;禁止两个下划线中间只 出现数字。数据库字段名的修改代价很大&#xff0c;因为无法进行预发布&#xff0c;所以字段名称需要慎重考虑。说明&#xff1a;MySQL 在 Windows 下不区…

数据库(11)-- Hash索引和BTree索引 的区别

索引是帮助mysql获取数据的数据结构。最常见的索引是Btree索引和Hash索引。 不同的引擎对于索引有不同的支持&#xff1a;Innodb和MyISAM默认的索引是Btree索引&#xff1b;而Mermory默认的索引是Hash索引。 Hash索引 哈希索引包含以数组形式组织的 Bucket 集合。 哈希函数将索…

JBoss AS 8中的Java EE 7和EJB 3.2支持

你们中有些人可能已经知道Java EE 7规范的Public Final Draft版本已经发布 。 除此以外&#xff0c;此版本的Java EE还引入了EJB规范的EJB 3.2版本。 与EJB 3.1规范相比&#xff0c;EJB 3.2具有一些新功能。 我在这里引用EJB 3.2规范中的文本&#xff0c;总结了新功能&#xff…

MySQL的复制:MySQL系列之十三

一、MySQL复制相关概念 主从复制&#xff1a;主节点将数据同步到多个从节点级联复制&#xff1a;主节点将数据同步到一个从节点&#xff0c;其他的从节点在向从节点复制数据同步复制&#xff1a;将数据从主节点全部同步到从节点时才返回给用户的复制策略叫同步复制异步复制&…

mysql与jframe_java-如何在JFrame上显示从mysql检索到的图像

我在显示从JFrame的数据库检索的图像时遇到问题.这是我将要使用的??????……try{Class.forName("com.mysql.jdbc.Driver");Connection conDriverManager.getConnection("jdbc:mysql://localhost:3306/studio","root","");Statem…

bootstrap到底是用来做什么的(概念)

Bootstrap官网&#xff1a;http://v3.bootcss.com/ Bootstrap是Twitter推出的一个用于前端开发的开源工具包。它由Twitter的设计师Mark Otto和Jacob Thornton合作开发,是一个CSS/HTML框架。 是一个做网页的框架&#xff08;目前最流行的WEB前端框架&#xff09;&#xff0c;就…

hdu 1020 Encoding

题目 这个题有一个挺坑的误区&#xff0c;不是统计字符串中出现的所有字符的个数&#xff0c;而是统计相邻的个数 刚开始就写错了 正解&#xff1a; #include <stdio.h> #include <string.h> int main(){int n,i,num;char str[10001];scanf("%d",&n)…

将NetBeans代码模板弯曲到我的意愿

任何阅读过我关于NetBeans的文章的人都知道&#xff0c;我真的很喜欢NetBeans的众多功能。 但是&#xff0c;最近&#xff0c;我发现自己对NetBeans特定功能的特定问题越来越恼火。 最终&#xff0c;它使我烦恼不已&#xff0c;促使我开始研究如何根据自己的喜好禁用或更改该功…

MySQL安装过程

最近试着重装了下MySQL&#xff0c;安装过程很简单&#xff0c;希望能帮助大家 mysql安装过程 1. 下载&#xff1a; 我下载的是64位系统的zip包&#xff1a; 下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 下载zip的包。 下载后解压到对应目录 如&#xff1a;D:…

极简的MyBatis在Spring Boot下的配置

以我的一个项目为例。 0、项目结构&#xff1a; 1、POM中添加MyBatis的依赖&#xff1a; <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.1</version> …

mysql sum很慢,可以在MySQL中加快sum()吗?

Im doing a "select sum(foo) from bar" query on a MySQL database thats summing up 7.3mm records and taking about 22 seconds per run. Is there a trick to speeding up sums in MySQL?解决方案No, you cant speed up the function itself. The problem here…

css常用属性总结:颜色和单位

在css代码编写中&#xff0c;估计颜色和单位是必不可少的&#xff0c;然而在css中关于颜色和单位值的写法有很多种写法&#xff0c;所以有必要把它弄清楚。 颜色 当初我在初学前端的时候&#xff0c;就会冒出一个疑问“我该如何设置网页颜色&#xff1f;”&#xff0c;一般常…

JPA –我应该成为懒惰的极端主义者吗?

当您与开发人员讨论将对象映射到关系数据库时&#xff0c;他们经常抱怨JPA性能差&#xff0c;JPA提供程序的行为不可预测等。通常&#xff0c;在对话的某些时候&#xff0c;您会听到&#xff1a; “让我们完全放弃这项技术&#xff0c;我们在上个月的会议上看到了更好的东西。 …

mysql恢复 报错_Mysql 数据恢复报错

1.测试mysql binlog 数据恢复功能&#xff0c;我的mysql版本是5.7.172.删了数据之后&#xff0c;执行show binlog events 命令得到如下记录3.找到开始删除和结束删除的位置&#xff0c;然后执行恢复命令:mysqlbinlog --no-defaults --start-position8991 --stop-position290468…

IONIC

1.项目摘要  随着移动互联网的不断发展&#xff0c;移动端流量所占比例已经越来越高。下图来自IResearch所做的关于移动互联网的市场调研报告 由此我们可以看出&#xff0c;移动互联网在人们生活中的位置越来越重要。 受益于国家“提速降费”以及即将取消流量漫游的优惠政策&…

line-height与图片底部间隙的学习整理转述

前言&#xff1a;这是笔者学习之后自己的理解与整理。如果有错误或者疑问的地方&#xff0c;请大家指正&#xff0c;我会持续更新&#xff01; 看大牛张鑫旭的视屏可能会理解的更深一些&#xff0c;点击这里&#xff1b; line-height&#xff0c;两行文字的基线之间的距离&…

java学习之异常之格式

第一个格式&#xff1a; try{}catch(){} 第二个格式&#xff1a; try{}catch(){}finally{} 第三个格式&#xff1a; try{}finally{} 注意&#xff1a;catch是用于处理异常&#xff0c;如果没有catch就代表异常没有被处理过&#xff0c;如果该异常是检测时异常&#xff0c;那么必…