原文

通过网络获取资源既缓慢又昂贵:

  • 大型响应需要浏览器和服务器之间的多次往返。
  • 直到所有关键资源都完全下载后,您的页面才会加载。
  • 如果一个人使用有限的移动数据计划访问您的网站,那么每个不必要的网络请求都是在浪费他们的钱。

如何避免不必要的网络请求? 浏览器的 HTTP 缓存是您的第一道防线。 它不一定是最强大或最灵活的方法,它对缓存响应的生命周期的控制有限,但它是有效的,所有浏览器都支持它,并且不需要太多工作。

实际上没有一个称为 HTTP 缓存的 API。 它是 Web 平台 API 集合的总称。 所有浏览器都支持这些 API:

  • Cache-Control
  • ETag
  • Last-Modified

HTTP cache 的工作原理

浏览器发出的所有 HTTP 请求都首先路由到浏览器缓存,以检查是否存在可用于满足请求的有效缓存响应。如果匹配,则从缓存中读取响应,从而消除网络延迟和传输产生的数据成本。

HTTP 缓存的行为由请求标头和响应标头的组合控制。在理想情况下,您可以控制 Web 应用程序的代码(将确定请求标头即 HTTP request headers)和 Web 服务器的配置(将确定响应标头即 HTTP response headers)。

Request headers: stick with the defaults (usually)

虽然有许多重要的标头应该包含在您的 Web 应用程序的传出请求中,但浏览器在发出请求时几乎总是代表您进行设置。 影响检查新鲜度的请求标头,如 If-None-Match 和 If-Modified-Since 只是基于浏览器对 HTTP 缓存中当前值的理解而出现。

这是个好消息——这意味着您可以继续在 HTML 中包含诸如下列例子之类的标签,并且浏览器会自动为您处理 HTTP 缓存,而无需额外的努力。

<img src="my-image.png">

Response headers: configure your web server

HTTP 缓存设置中最重要的部分是您的 Web 服务器添加到每个传出响应的标头。 以下标头都会影响有效的缓存行为:

  • Cache-control: 服务器可以返回一个 Cache-Control 指令来指定浏览器和其他中间缓存应该如何缓存单个响应以及缓存多长时间。

  • ETAG: 当浏览器发现过期的缓存响应时,它可以向服务器发送一个小令牌(通常是文件内容的哈希)以检查文件是否已更改。 如果服务器返回相同的令牌,则文件是相同的,无需重新下载。

  • Last-Modified: 此标头与 ETag 的用途相同,但使用基于时间的策略来确定资源是否已更改,这与 ETag 的基于内容的策略相反。

默认情况下,某些 Web 服务器内置支持设置这些标头,而其他 Web 服务器则完全保留标头,除非您明确配置它们。 如何配置标头的具体细节因您使用的 Web 服务器而异,您应该查阅服务器的文档以获得最准确的详细信息。

省略 Cache-Control 响应标头不会禁用 HTTP 缓存! 相反,浏览器有效地猜测哪种类型的缓存行为对给定类型的内容最有意义。 您可能需要更多的控制权,因此请花时间配置您的响应标头。

在配置 Web 服务器的响应标头时,您应该涵盖两个重要的场景。

Long-lived caching for versioned URLs

假设您的服务器指示浏览器将 CSS 文件缓存 1 年(Cache-Control: max-age=31536000),但您的设计人员刚刚进行了一个需要立即推出的紧急更新。您如何通知浏览器更新文件的“陈旧”缓存副本?你不能,至少不能不改变资源的 URL。在浏览器缓存响应后,缓存版本将一直使用,直到它不再是最新的,这由 max-age 或 expires 决定,或者直到它因某些其他原因从缓存中被驱逐——例如,用户清除他们的浏览器缓存。因此,在构建页面时,不同的用户最终可能会使用不同版本的文件:刚刚获取资源的用户使用新版本,而缓存较早(但仍然有效)副本的用户使用其旧版本回复。您如何获得两全其美:客户端缓存和快速更新?您更改资源的 URL 并强制用户在其内容更改时下载新响应。通常,您可以通过在文件名中嵌入文件的指纹或版本号来实现这一点,例如 style.x234dff.css。

当响应包含“指纹”或版本信息且其内容永远不会改变的 URL 请求时,请将 Cache-Control: max-age=31536000 添加到您的响应中。

设置这个值告诉浏览器,当它需要在接下来的一年内的任何时候(31,536,000 秒;支持的最大值)加载相同的 URL 时,它可以立即使用 HTTP 缓存中的值,而无需向网络发出请求 你的网络服务器。 太好了 - 您立即获得了避免网络带来的可靠性和速度!

像 webpack 这样的构建工具可以自动化将哈希指纹分配给资产 URL 的过程。

Server revalidation for unversioned URLs

不幸的是,并非您加载的所有 URL 都是版本化的。

也许您无法在部署 Web 应用程序之前包含构建步骤,因此您无法向资产 URL 添加哈希值。 并且每个 Web 应用程序都需要 HTML 文件——这些文件(几乎!)永远不会包含版本信息,因为如果他们需要记住要访问的 URL 是 https://example.com,那么没有人会费心使用您的 Web 应用程序 /index.34def12.html。 那么你能对这些 URL 做些什么呢?

这是您需要承认失败的一种情况。 单独的 HTTP 缓存不足以完全避开网络 request. 但是你可以采取一些步骤来确保网络请求尽可能快, 并尽可能高效。

以下 Cache-Control 值可以帮助您微调未版本控制的 URL 的缓存位置和方式:

  • no-cache: 这会指示浏览器每次使用 URL 的缓存版本之前都必须与服务器重新验证。
  • no-store: 这会指示浏览器和其他中间缓存(如 CDN)从不存储文件的任何版本。
  • private: 浏览器可以缓存文件,但中间缓存不能。
  • public: 响应可以由任何缓存存储。

Etag 使用例子

浏览器从服务器请求 /file 并包含 If-None-Match 标头以指示服务器仅在服务器上文件的 ETag 与浏览器的 If-None-Match 值不匹配时才返回完整文件。 在这种情况下,这 2 个值确实匹配,因此服务器返回 304 Not Modified 响应,并说明文件应缓存多长时间(Cache-Control: max-age=120)。

总结

HTTP Cache 是一种提高负载性能的有效方式,因为它减少了不必要的网络请求。 它在所有浏览器中都受支持,并且不需要太多设置。

以下 Cache-Control 配置是一个好的开始:

  • Cache-control: no-cache - 对于每次使用前应与服务器重新验证的资源

  • Cache-control:no-store: - 不应该缓存的资源

  • Cache-control: max-age=31536000:版本化资源

使用 HTTP 缓存防止不必要的网络请求相关推荐

  1. Android okHttp网络请求之缓存控制Cache-Control

    前言: 前面的学习基本上已经可以完成开发需求了,但是在项目中有时会遇到对请求做个缓存,当没网络的时候优先加载本地缓存,基于这个需求我们来学习一直okHttp的Cache-Control. okHttp ...

  2. Android应用中网络请求库Volley的使用

    接上文,这次来说一下如何使用Volley,会给出一些范例,和原理 Volley使用 StringRequest // 初始化一个请求队列,RequestQueue是volley库的类 RequestQ ...

  3. Android 网络请求详解

    我们知道大多数的 Android 应用程序都是通过和服务器进行交互来获取数据的.如果使用 HTTP 协议来发送和接收网络数据,就免不了使用 HttpURLConnection 和 HttpClient ...

  4. Volley网络请求框架简析——Android网络请求框架(三)

    题记-- 人来到这个世界上,只有两件事情,生与死, 一件事完了,另一件事还急什么? 有缘而来,无缘而去, 识自本心,见自本性 不起妄缘,无心无为 自由自在,动静自如 冷暖自知,则是修行 1.初始化一个 ...

  5. 详解 Android okhttp 网络请求get,post传输数据的基本用法

    官网网址:http://square.github.io/okhttp/ github地址:https://github.com/square/okhttp OKHttp优点 1.支持HTTP2/SP ...

  6. android okgo 网络请求框架

    OkGo - OkHttpUtils-2.0.0升级后改名 OkGo,全新完美支持RxJava 项目地址:https://github.com/jeasonlzy,欢迎star,欢迎issue 该库是 ...

  7. 你想要的系列:网络请求框架OkHttp3全解系列 - (二)OkHttp的工作流程分析

    Okhttp系列文章: 你想要的系列:网络请求框架OkHttp3全解系列 - (一)OkHttp的基本使用 你想要的系列:网络请求框架OkHttp3全解系列 - (二)OkHttp的工作流程分析 你想 ...

  8. android xutils json请求,Android Xutils3网络请求的封装详解及实例代码

    Xutils3网络请求的封装详解 封装了一个Xutil3的网络请求工具类,分享给大家,本人水平有限,不足之处欢迎指出. 使用前先配置xutils3: 1.gradle中添加 compile 'org. ...

  9. 流行框架(二)网络请求库 OKhttp

    文章目录 概述 HttpURLConnection GET和POST获取文本数据 GET POST OKHttp 基本使用 依赖与权限 发起一个get请求 重要概念 OkHttpClient Requ ...

最新文章

  1. java instanceof 报错_java instanceof方法
  2. emq插件开发mysql_EMQ的Mysql插件
  3. 博图如何读取mysql数据_博途使用小结:从SQL中读取数据并给变量赋值
  4. 离散数学实验题目-图
  5. php manager iis 8,PHPManager2下载
  6. template里面要做数据渲染,但是数据还没有出来
  7. 旅行线路定制主题响应式手机模板
  8. MySQL SQL语句知识点总结
  9. 怎么在linux终端上sed,Linux中如何使用sed命令
  10. 剑指offer面试题[7]-用两个栈实现队列
  11. 解决安卓全屏问题:关键在于如何隐藏状态栏
  12. 计算机重装后如何连接无线网络,电脑重装系统后无线网络连接不上怎么办
  13. 经济寒冬之后,是人工智能的春天
  14. 《安富莱嵌入式周报》第285期:电子技术更新换代太快,我要躺平,Linux内核6.1已经并入RUST,一夜161个网站密码遭泄,Matlab精选课件,开源电子书
  15. 图像修复模型——TV模型
  16. 用QuartusII 操作操作1位全加法器单位延时仿真
  17. Working Practice-破窗理论与写代码
  18. storm笔记:Trident应用
  19. 导出的excel表格是乱码的解决方法
  20. WINOWS server2008 安装microsoft windows 恶意软件删除工具 (kb890830)

热门文章

  1. 按钮设置成透明的方法
  2. [算法总结] 二分查找
  3. 如何在SAP CRM WebClient UI里创建HANA Live Report
  4. puppet kick 功能实现
  5. 如何使用新的邮件传输规则和邮件策略
  6. frame,iframe,frameset 的区别
  7. 【CI】CN.一种多尺度协同变异的微粒群优化算法
  8. Mybatis的下载并搭建核心架构
  9. Hello,PyQt5!
  10. MenuItem创建注意事项