HTTP缓存机制 & cookie/localStorage/sessionStorage

web缓存大致可以分为:数据库数据缓存、服务器端缓存(代理服务器缓存、CDN缓存)、浏览器端缓存、web应用层缓存。

其中,浏览器端缓存的机制种类:HTTP缓存机制、浏览器本地存储(cookie 、localStorage、sessionStorage、webSQL、indexDB、……)如下图所示:

浏览器本地存储

本文主要着重讲解浏览器本地存储(cookie 、localStorage、sessionStorage) 以及 HTTP缓存机制。


浏览器本地存储

Cookie

Cookie(或者Cookies),指某些网站为了辨别用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)

  • cookie一般通过http请求中在头部一起发送到服务器端。
  • 一条cookie记录主要由键、值、域、过期时间、大小组成,一般用户保存用户的认证信息。
  • Cookie是为了解决HTTP无状态的特性而出现的,也可以叫用户识别机制。

sessionStorage 和 localStorage

Web Storage 是指 HTML5 的本地存储 API sessionStorage 和 localStorage。

  • Web Storage 是通过存储字符串的 Key/Value 对来提供的,并提供 5MB (不同浏览器可能不同,分 HOST)的存储空间,如果数据存放超过最大限制会报错,并移除最先保存的数据。
  • Web Storage 分为 sessionStorage 和 localStorage。localStorage 对象和 sessionStorage 对象使用方法基本相同,它们的区别在于作用的范围不同。sessionStorage用来存储与页面相关的数据,它在页面关闭后无法使用。而 localStorage则持久存在,在页面关闭后也可以使用

Cookie VS Web Storage

Cookie & Web Storage 异同点

Cookie VS Session

Cookie VS Session 异同点

HTTP缓存机制

概述

从缓存位置上来说分为四种,优先级依次是:
Memory Cache、Service Worker Cache、Disk Cache、Push Cache


浏览器缓存
  • MemoryCache,是指存在内存中的缓存。从优先级上来说,它是浏览器最先尝试去命中的一种缓存。从效率上来说,它是响应速度最快的一种缓存。浏览器秉承的是“节约原则”,我们发现,Base64 格式的图片,几乎永远可以被塞进 memory cache,这可以视作浏览器为节省渲染开销的“自保行为”;此外,体积不大的 JS、CSS 文件,也有较大地被写入内存的几率——相比之下,较大的 JS、CSS 文件就没有这个待遇了,内存资源是有限的,它们往往被直接甩进磁盘。一旦我们关闭 Tab 页面,内存中的缓存也就被释放了。
  • Service Worker, 是一种独立于主线程之外的 Javascript 线程。它脱离于浏览器窗体,因此无法直接访问 DOM。这样独立的个性使得 Service Worker 的“个人行为”无法干扰页面的性能,这个“幕后工作者”可以帮我们实现离线缓存、消息推送和网络代理等功能。我们借助 Service worker 实现的离线缓存就称为 Service Worker Cache。
  • Disk Cache(HTTP Cache),Disk Cache 也就是存储在硬盘中的缓存,读取速度慢点,但是什么都能存储到磁盘中,比之 Memory Cache 胜在容量和存储时效性上。在所有浏览器缓存中,Disk Cache 覆盖面基本是最大的。它会根据 HTTP Header 中的字段判断哪些资源需要缓存,哪些资源可以不请求直接使用,哪些资源已经过期需要重新请求。并且即使在跨站点的情况下,相同地址的资源一旦被硬盘缓存下来,就不会再次去请求数据。绝大部分的缓存都来自 Disk Cache,关于 HTTP 的协议头中的缓存字段,我们会在下文进行详细介绍。它又分为强缓存和协商缓存。
  • Push Cache,Push Cache 是指 HTTP2 在 server push 阶段存在的缓存。
    • Push Cache 是缓存的最后一道防线。浏览器只有在 Memory Cache、HTTP Cache 和 Service Worker Cache 均未命中的情况下才会去询问 Push Cache。
    • Push Cache(推送缓存) 是一种存在于会话阶段的缓存,当 session 终止时,缓存也随之释放。
    • 不同的页面只要共享了同一个 HTTP2 连接,那么它们就可以共享同一个 Push Cache。

浏览器端的缓存规则

  • 新鲜度(过期机制):也就是缓存副本有效期。一个缓存副本必须满足以下任一条件,浏览器会认为它是有效的,足够新的,而直接从缓存中获取副本并渲染:
    • 含有完整的过期时间控制头信息(HTTP协议报头),并且仍在有效期内
    • 浏览器已经使用过这个缓存副本,并且在一个会话中已经检查过新鲜度
  • 校验值(验证机制):服务器返回资源的时候有时在控制头信息带上这个资源的实体标签Etag(Entity Tag),它可以用来作为浏览器再次请求过程的校验标识。如过发现校验标识不匹配,说明资源已经被修改或过期,浏览器需求重新获取资源内容。

浏览器缓存的控制

分别从新鲜度和校验值两个维度来规定浏览器是否可以直接使用缓存中的副本,还是需要去源服务器获取更新的版本。


常见的与缓存有关的消息报头
if (Cache-Control === no-store) {
  // 绝对禁止缓存,浏览器本地不会进行缓存,每次请求资源都要从服务器重新获取。
 直接向服务器获取资源(本地不缓存资源)
} else if (Cache-Control === no-cache) {
  // 设置了 no-cache 之后并不代表浏览器不缓存,而是在获取缓存前要向服务器确认资源是否被更改。
 每次请求都向服务器确认资源是否被更改(本地缓存资源),走下面的协商缓存
} else if (本地未过期 => max-age || Expires) {
  使用浏览器本地缓存
} else { // 协商缓存
  if (ETag有值) {

      向服务器请求带if-None-Match

      if (ETag与原来的一致) {
        返回304,直接使用本地缓存
      } else {
        返回200,获取新资源
      }
  } else if (Last-modified有值) {

      向服务器请求带if-Modified-Since

      if (Last-modified与原来的一致) {
        返回304,直接使用本地缓存
      } else {
        返回200,获取新资源
      }
  } else {
      向服务器获取新资源,返回200
 }
}

缓存流程

以上过程也可以被概括为三个阶段:

  • 本地缓存阶段(也称强缓存):先在本地查找该资源,如果有发现该资源,而且该资源还没有过期,就使用这一个资源,完全不会发送http请求到服务器;
  • 协商缓存阶段(也称弱缓存):如果在本地缓存找到对应的资源,但是不知道该资源是否过期或者已经过期,则发一个http请求到服务器,然后服务器判断这个请求,如果请求的资源在服务器上没有改动过,则返回304,让浏览器使用本地找到的那个资源;
  • 缓存失败阶段:当服务器发现请求的资源已经修改过,或者这是一个新的请求(在本来没有找到资源),服务器则返回该资源的数据,并且返回200, 当然这个是指找到资源的情况下,如果服务器上没有这个资源,则返回404。

详细信息——缓存有关的HTTP消息报头

Cache-Control
  • max-age(单位为s)指定设置缓存最大的有效时间,定义的是时间长短。当浏览器向服务器发送请求后,在max-age这段时间里浏览器就不会再向服务器发送请求了。
  • s-maxage(单位为s)同max-age,只用于共享缓存(比如CDN缓存)。比如,当s-maxage=60时,在这60秒中,即使更新了CDN的内容,浏览器也不会进行请求。也就是说max-age用于普通缓存,而s-maxage用于代理缓存。如果存在s-maxage,则会覆盖掉max-age和Expires header。
  • no-cache 指定不缓存响应,表明资源不进行缓存,但是设置了 no-cache 之后并不代表浏览器不缓存,而是在获取缓存前要向服务器确认资源是否被更改。因此有的时候只设置 no-cache 防止缓存还是不够保险,还可以加上 private 指令,将过期时间设为过去的时间。(no-cache 绕开了浏览器:我们为资源设置了 no-cache 后,每一次发起请求都不会再去询问浏览器的缓存情况,而是直接向服务端去确认该资源是否过期,即走协商缓存的路线)
  • no-store 绝对禁止缓存,如果用了这个命令就是不会进行缓存每次请求资源都要从服务器重新获取。(no-store 比较绝情,顾名思义就是不使用任何缓存策略。在 no-cache 的基础上,它连服务端的缓存确认也绕开了,只允许你直接向服务端发送请求、并下载完整的响应。)
Cache-Control与Expires

Cache-Control与 Expires的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。只不过 Cache-Control的选择更多,设置更细致,如果同时设置的话,其优先级高于 Expires

public 与 private

public 与 private 是针对资源是否能够被代理服务缓存而存在的一组对立概念。如果我们为资源设置了 public,那么它既可以被浏览器缓存,也可以被代理服务器缓存;如果我们设置了 private,则该资源只能被浏览器缓存。private 为默认值。

Last-Modified与ETag

Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。

Last-Modified/ETag 与 Cache-Control/Expires
  • 配置 Last-Modified/ETag的情况下,浏览器再次访问统一URI的资源,还是会发送请求到服务器询问文件是否已经修改,如果没有,服务器会只发送一个304回给浏览器,告诉浏览器直接从自己本地的缓存取数据;如果修改过那就整个数据重新发给浏览器;
  • Cache-Control/Expires则不同,如果检测到本地的缓存还是有效的时间范围内,浏览器直接使用本地副本,不会发送任何请求。两者一起使用时, Cache-Control/Expires的优先级要高,即当本地副本根据 Cache-Control/Expires发现还在有效期内时,则不会再次发送请求去服务器询问修改时间 Last-Modified或实体标识 Etag了。
  • 一般情况下,两者会配合一起使用,因为即使服务器设置缓存时间, 当用户点击“刷新”按钮时,浏览器会忽略缓存继续向服务器发送请求,这时 Last-Modified/ETag将能够很好利用304,从而减少响应开销。
有Last-Modified为什么还要有ETag?

HTTP1.1中Etag的出现主要是为了解决几个 Last-Modified 比较难解决的问题:

  • Last-Modified 标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的新鲜度
  • 如果某些文件会被定期生成,当有时内容并没有任何变化,但 Last-Modified 却改变了,导致文件没法使用缓存
  • 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形
用户操作行为与缓存的关系
用户操作行为与缓存的关系

参考链接:
你必须懂的前端性能优化
浏览器缓存机制全攻略
Web缓存相关知识整理
9大浏览器端缓存机制分析
深入理解浏览器的缓存机制

推荐文章:
前端开发之走进Vue.js(入门知识点)
《你不知道的javascript上卷》摘要(上)
《你不知道的javascript上卷》摘要(下)
Git使用总结
如何在Vue+Webpack下配置Stylelint
Highchart属性笔记

原文:HTTP缓存机制 & cookie/localStorage/sessionStorage

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容

  • 网络特有的延迟以及数据传输的成本,制约互联网快速获取Web资源。为此,HTTP协议引入缓存以空间换时间,使浏览器缓...
    大头8086阅读 3,031评论 2 12
  • 浏览器对于请求资源, 流程如图所示: 可以看到浏览器的缓存机制分为两个部分: 1、当前缓存是否过期? 2、服务器中...
    zhoulujun阅读 1,162评论 0 3
  • 参考《深入理解浏览器的缓存机制》进行整理 前言 缓存可以说是性能优化中简单高效的一种优化方式了。一个优秀的缓存策略...
    琢磨先生lf阅读 735评论 1 1
  • 最近在项目中遇到了 IE浏览器因缓存问题未能成功向后端发送 GET类型请求 的bug,然后顺藤摸瓜顺便看了看缓存的...
    殖民_FE阅读 612评论 0 1
  • 一、前言 缓存可以说是性能优化中简单高效的一种优化方式了。一个优秀的缓存策略可以缩短网页请求资源的距离,减少延迟,...
    沉落的星星阅读 381评论 0 0