前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >前端网络高级篇(三)浏览器缓存

前端网络高级篇(三)浏览器缓存

作者头像
娜姐
发布2022-01-20 12:43:47
7850
发布2022-01-20 12:43:47
举报
文章被收录于专栏:娜姐聊前端娜姐聊前端

浏览器缓存有多种形式,持久化或者会话存储。以chrome为例,打开调试面板,找到Application选项卡,就可以看到它所支持的各种缓存模式

缓存方式

详解

使用情况

http缓存

分为强缓存(200)和协商缓存(304),文章后面有详细介绍

强烈推荐

localstorge

本地缓存单个域名下有大小限制(最大5M)同一域名多个页面共享

推荐

sessionstorage

本地缓存页面关闭时清空

-

cookie

不支持跨域(同localstorge)可通过设置domain和path实现共享域名分为session cookie(关闭浏览器清空)和持久性cookie(定义有效期)httponly设置为true时,JS无法获取cookie值常用于身份验证(逐渐被token替代)

-

webSQL

非HTML5规范,是一种特定的浏览器特性集成在浏览器中的本地数据库类似NoSQL数据库

不推荐

indexDB

HTML5规范50M限制浏览器支持情况不佳

推荐-还需等等

Application Cache

通过manifest配置文件在本地有选择性的存储JS/CSS/图片等静态资源存储大小:5M静态资源必须和HTML文件同源逐渐被Service Worker替代

不推荐

Cache Storage

ServiceWorker 规范中定义的离线方案设置window全局内置对象caches浏览器兼容性较差

推荐-还需等等

下面,重点介绍HTTP缓存。

1. HTTP缓存

一般,浏览器只对GET请求开启缓存。HTTP缓存存在于浏览器和Web代理中。当然在服务器内部,也存在着各种缓存。代理缓存和服务器缓存不予关心。

image

HTTP缓存分为两大类:

  • 强缓存:浏览器直接从自己的缓存中读取资源,不会发请求到服务器;
  • 协商缓存:当强缓存没有命中的时候,浏览器一定会发送一个请求到服务器,通过服务器端依据资源的另外一些http header验证这个资源是否命中协商缓存,如果协商缓存命中,服务器会将这个请求返回,但是不会返回这个资源的数据,而是告诉客户端可以直接从缓存中加载这个资源,于是浏览器就又会从自己的缓存中去加载这个资源;

两者的区别:强缓存不发请求到服务器,协商缓存会发请求到服务器。 两者的共同点:都是从客户端缓存中加载资源。

我们经常会刷新浏览器,不同的刷新方式对缓存有不同影响:

  • 当ctrl+f5强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存;
  • 当f5刷新网页时,跳过强缓存,但是会检查协商缓存;

协商缓存并非是一种被强缓存“低级”的策略,对于一些特殊的应用场景或资源,协商缓存优于强缓存。 比如,单页面项目中,每次发布JS和CSS文件都可能发生变化(通过在文件名上加hash来指定变化),那么,必须保证每次请求到的HTML文件必须是最新的。为了便于服务器解析和网站地址的唯一性,我们又不能在HTML文件上应用hash指纹。在这种场景下,就只能使用协商缓存了。

2. 强缓存

强缓存是利用Expires或者Cache-Control这两个http response header实现的,它们都用来表示资源在客户端缓存的有效期。

代码语言:javascript
复制
当浏览器对某个资源的请求命中了强缓存时,返回的http状态为200。在chrome的开发者工具的network里面size会显示为from cache。

image

强缓存会有3种命中模式:from memory cachefrom disk cache资源本身的大小(如:1.5k)。三种区别在哪?(参考:from memory cache与from disk cache详解)

方式

详解

备注

from memory cache

该资源直接从内存中拿到的,前提:服务器已经加载过该资源且缓存在了内存当中。当关闭该页面时,此资源就被内存释放掉了,再次重新打开相同页面时不会出现from memory cache的情况

一般脚本、字体、图片会存在内存当中

from disk cache

该资源从磁盘当中取出的,前提:之前的某个时间加载过该资源,不会请求服务器但是此资源不会随着该页面的关闭而释放掉,因为是存在硬盘当中的,下次打开仍会from disk cache

一般非脚本会存在内存当中,如css等

资源本身大小数值

当http状态为200是实实在在从浏览器获取的资源,当http状态为304时该数字是与服务端通信报文的大小,并不是该资源本身的大小,该资源是从本地获取的

-

  • 问题:如何管理强缓存呢? 答案:可以在在web服务器上配置,或者通过代码方式,在web服务器返回响应中配置。
  • 问题:如何清除强缓存呢? 答案:有几种方案可以选。
    1. ctrl+F5
    2. 浏览器隐身模式
    3. chrome在network标签下禁止缓存
    4. 在开发阶段,给资源加上一个动态的参数,如css/index.css?v=0.0001,由于每次资源的修改都要更新引用的位置,同时修改参数的值。
    5. 如果缓存问题出现在ajax请求中,最有效的解决办法就是ajax的请求地址追加随机数;
2.1 强缓存:Expires

Expires是http1.0提出的一个表示资源过期时间的header,它描述的是一个绝对时间,由服务器返回,用GMT格式的字符串表示,如:Expires:Thu, 31 Dec 2037 23:55:55 GMT,它的缓存原理是:

  1. 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在respone header加上Expires属性,如:
  1. 浏览器在接收到这个资源后,会把这个资源连同所有response header一起缓存下来;
  2. 浏览器再请求这个资源时,先从缓存中寻找,找到这个资源后,拿出它的Expires跟当前的请求时间比较,如果请求时间在Expires指定的时间之前,就能命中缓存,否则就不行。
  3. 如果缓存没有命中,浏览器直接从服务器加载资源时,Expires Header在重新加载的时候会被更新。

缺点: 由于它是服务器返回的一个绝对时间,在服务器时间与客户端时间相差较大时,缓存管理容易出现问题。 比如随意修改下客户端时间,就能影响缓存命中的结果。

2.2 强缓存:Cache-Control:max-age

http1.1的时候,提出了一个新的header:Cache-Control,这是一个相对时间,在配置缓存的时候,以秒为单位,用数值表示,如:Cache-Control:max-age=315360000,它的缓存原理是:

  1. 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在respone header加上Cache-Control属性,如:
  1. 浏览器在接收到这个资源后,会把这个资源连同所有response header一起缓存下来;
  2. 浏览器再请求这个资源时,先从缓存中寻找,找到这个资源后,根据它第一次的请求时间和Cache-Control设定的有效期,计算出一个资源过期时间,再拿这个过期时间跟当前的请求时间比较,如果请求时间在过期时间之前,就能命中缓存,否则就不行。
  3. 如果缓存没有命中,浏览器直接从服务器加载资源时,Cache-Control Header在重新加载的时候会被更新。

优点: Cache-Control描述的是一个相对时间,在进行缓存命中的时候,都是利用客户端时间进行判断, 所以相比较Expires,Cache-Control的缓存管理更有效,安全一些。

如果同时启用Expires和Cache-Control, Cache-Control优先级高于Expires。

3. 协商缓存

当浏览器对某个资源的请求没有命中强缓存,就会发一个请求到服务器,验证协商缓存是否命中,如果协商缓存命中,请求响应返回的http状态为304并且会显示一个Not Modified的字符串。

image

image

协商缓存是利用的是Last-ModifiedIf-Modified-Since或者ETagIf-None-Match这两对Header来管理的。

3.1 协商缓存 Last-Modified,If-Modified-Since

1). 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在respone header加上Last-Modified属性(表示这个资源在服务器上的最后修改时间):

image

2). 浏览器再次跟服务器请求这个资源时,在request header上加上If-Modified-Since属性(该值就是上一次请求时返回的Last-Modified的值):

image

3). 服务器再次收到资源请求时,根据浏览器传过来If-Modified-Since和资源在服务器上的最后修改时间判断资源是否有变化,如果没有变化则返回304 Not Modified,但是不会返回资源内容;如果有变化,就正常返回资源内容。

当服务器返回304 Not Modified的响应时,response header中不会再添加Last-Modified,因为既然资源没有变化,那么Last-Modified也就不会改变,这是服务器返回304时的response essay-header:

image

4). 浏览器收到304的响应后,就会从缓存中加载资源。

5). 如果协商缓存没有命中,浏览器直接从服务器加载资源时,Last-Modified Header在重新加载的时候会被更新,下次请求时,If-Modified-Since会启用上次返回的Last-Modified值。

缺点: 和Expire类似,一般来说,在没有调整服务器时间和篡改客户端缓存的情况下,这两个essay-header配合起来管理协商缓存是非常可靠的, 但是有时候也会服务器上资源其实有变化,但是最后修改时间却没有变化的情况,就会影响协商缓存的可靠性。

3.2 协商缓存 ETag, If-None-Match

1). 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在respone header加上ETag。

ETag是服务器根据当前请求的资源生成的一个唯一标识。 这个唯一标识是一个字符串,只要资源有变化这个串就不同,跟最后修改时间没有关系。

image

2). 浏览器再次跟服务器请求这个资源时,在request header上加上If-None-Match(值就是上一次请求时返回的ETag的值)。 3). 服务器再次收到资源请求时,根据浏览器传过来If-None-Match和然后再根据资源生成一个新的ETag,如果这两个值相同就说明资源没有变化,否则就是有变化; 如果没有变化则返回304 Not Modified,但是不会返回资源内容; 如果有变化,就正常返回资源内容。 与Last-Modified不一样的是,当服务器返回304 Not Modified的响应时,由于ETag重新生成过,response header中还会把这个ETag返回,即使这个ETag跟之前的没有变化。

image

如上例中所示,在使用了If-None-Match之后,可以更加准确的更新文件缓存时间。

但是,Etag 的生成过程需要服务器额外付出开销,会影响服务端的性能,这是它的弊端。因此启用 Etag 需要我们审时度势。 Etag 并不能替代 Last-Modified,它只能作为 Last-Modified 的补充和强化存在。 Etag 在感知文件变化上比 Last-Modified 更加准确,优先级也更高。当 Etag 和 Last-Modified 同时存在时,以 Etag 为准

4. 响应头Cache-Control

每个资源都可以通过Http头Cache-Control来定义自己的缓存策略,Cache-Control控制谁在什么条件下可以缓存响应以及可以缓存多久。 最快的请求是不必与服务器进行通信的请求:通过响应的本地副本,我们可以避免所有的网络延迟以及数据传输的数据成本。为此,HTTP 规范允许服务器返回一系列不同的 Cache-Control 指令,控制浏览器或者其他中继缓存如何缓存某个响应以及缓存多长时间。

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

Cache-Control中设置的常用指令如下: max-age(强缓存):该指令指定从当前请求开始,允许获取的响应被重用的最长时间(单位为秒。例如:Cache-Control:max-age=60表示响应可以再缓存和重用 60 秒。需要注意的是,在max-age指定的时间之内,浏览器不会向服务器发送任何请求,包括验证缓存是否有效的请求,也就是说,如果在这段时间之内,服务器上的资源发生了变化,那么浏览器将不能得到通知,而使用老版本的资源。所以在设置缓存时间的长度时,需要慎重。

public和private:如果设置了public,表示该响应可以在浏览器或者任何中继的Web代理中缓存,public是默认值,即Cache-Control:max-age=60等同于Cache-Control:public, max-age=60。

no-cache(协商缓存):如果服务器在响应中设置了no-cache,即Cache-Control:no-cache,那么浏览器在使用缓存的资源之前,必须先与服务器确认返回的响应是否被更改,如果资源未被更改,可以避免下载。这个验证之前的响应是否被修改,就是通过上面介绍的请求头If-None-match和响应头ETag来实现的。

设置了no-cache之后,并不是说浏览器就不再缓存数据,只是浏览器在使用缓存数据时,需要先确认一下数据是否还跟服务器保持一致。

no-store(不缓存):如果服务器在响应中设置了no-store,即Cache-Control:no-store,那么浏览器和任何中继的Web代理,都不会存储这次相应的数据。当下次请求该资源时,浏览器只能重新请求服务器,重新从服务器读取资源。

5. HTTP缓存小结

在HTTP1.1协议下,HTTP缓存流程如下所示。

image

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020.06.09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. HTTP缓存
  • 2. 强缓存
    • 2.1 强缓存:Expires
      • 2.2 强缓存:Cache-Control:max-age
      • 3. 协商缓存
        • 3.1 协商缓存 Last-Modified,If-Modified-Since
          • 3.2 协商缓存 ETag, If-None-Match
          • 4. 响应头Cache-Control
          • 5. HTTP缓存小结
          相关产品与服务
          云开发 CLI 工具
          云开发 CLI 工具(Cloudbase CLI Devtools,CCLID)是云开发官方指定的 CLI 工具,可以帮助开发者快速构建 Serverless 应用。CLI 工具提供能力包括文件储存的管理、云函数的部署、模板项目的创建、HTTP Service、静态网站托管等,您可以专注于编码,无需在平台中切换各类配置。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档