缓存:浏览器缓存、DNS缓存和CDN缓存

代码已经关联到github: 链接地址 文章有更新也会优先在这,觉得不错可以顺手点个star,这里会持续分享自己的开发经验(:

浏览器缓存

浏览器再次发送请求时:

  1. 首先判断强缓存,强缓存生效直接使用强缓存(200 from memory、from disk 先从内存,再从硬盘)
  2. 如果强缓存不生效会判断
    1. 没有设置协商缓存就直接重新请求(200)
    2. 设置了协商缓存则由服务器判断缓存是否失效,没有失效就继续使用缓存(304,同强缓存的获取方式),失效则返回新的文件(200)

缓存分类

强缓存

强缓存主要由响应消息头 Cache-ControlExpires 两个 Header 决定的,在一定时间内不向后端请求,直接使用内存或者磁盘内的缓存内容,前者的优先级更高。

Cache-Control: max-age=31536000 //缓存时间 | no-store:禁止本地缓存 | no-cache:本地缓存,但是强制每次请求直接发送给源服务器,由服务器判断是否使用缓存
Cache-Control: private;max-age=31536000 //默认是public 允许代理
Expires: Wed, 21 Oct 2020 07:28:00 GMT //该时间之后请求过期 Cache-control 优先级比 Expires 优先级高

注意请求头的消息头也可以设置Cache-Control , 表示客户端想要的缓存策略是什么。

一般不经常变动的JS和CSS均会有一个很大的过期时间,搭配上版本号进行缓存策略,减少向后端的请求,如果均不设置只带版本号也可以,因为浏览器自动有缓存的策略。

有些时候,我们会看到Cache-Control: max-age=31536000,那么浏览器帧的会缓存这个数据到一年吗,答案当然是否定的,设置这个值只是因为它是协议允许的最大值,浏览器不会缓存那么久,当缓存满了会优先删除旧的内容,但是CDN会,这样可以减少服务器的压力。

协商缓存

If-none-match/ETagsIf-Modified-Since/Last-Modified 参数决定,通常在强缓存失效后,向服务端通信,服务端确定是否使用缓存,前者优先级更高。

  • ETags 是服务器资源的一个唯一标识,请求响应时消息头会带上这个唯一标识,请求头带上上次请求返回的etag(If-none-match ),由服务器判断资源是否改变。
  • 请求响应时时消息头会带上上次修改时间(Last-Modified),请求时消息头会带上这个修改时间(If-Modified-Since ),由服务器判断资源是否改变。

对于频繁变动的资源,服务器端需设置Cache-Control: no-cache 使浏览器每次都请求服务器,且增加返回请求头 ETag 或者 Last-Modified 来验证资源是否有效。这样的做法虽然不能节省请求数量,但是能显著减少响应数据大小。

版本号
  • revving 技术 : 不频繁更新的文件会使用特定的命名方式:在 URL 后面(通常是文件名后面)会加上版本号。
Service Work

一个服务器与浏览器之间的中间人角色,如果网站中注册了service worker那么它可以拦截当前网站所有的请求,进行判断(需要编写相应的判断程序),如果需要向服务器发起请求的就转给服务器,如果可以直接使用缓存的就直接返回缓存不再转给服务器。

简单使用

Service Worker是浏览器在后台独立于网页运行的、用JavaScript编写的脚本。
让我们来看看最小的Service Worker长什么样,以及怎么跑起来:

// 不起眼的一行if,除了防止报错之外,也无意间解释了PWA的P:
// 如果浏览器不支持Service Worker,那就当什么都没有发生过
if ('serviceWorker' in navigator) {
    window.addEventListener('load', function () {
        // 所以Service Worker只是一个挂在navigator对象上的HTML5 API而已
        // scope 参数是可选的,可以用来指定你想让 service worker 控制的内容的子目录。 在这个例子里,我们指定了 '/',表示 根网域下的所有内容。这也是默认值。 
        navigator.serviceWorker.register('/service-worker.js', {scope: './'}).then(function (registration) {
            console.log('我注册成功了');
        }, function (err) {
            console.log('我注册失败了');
        });
    });
}

复制代码以上代码,在load事件触发后,下载并注册了service-worker.js这个文件,Service Worker的逻辑,就写在这里:

// service-worker.js
// 虽然可以在里边为所欲为地写任何js代码,或者也可以什么都不写,
// 都不妨碍这是一个Service Worker,但还是举一个微小的例子:

//监听安装事件,install 事件一般是被用来设置你的浏览器的离线缓存逻辑
this.addEventListener('install', function(event) {
  //通过这个方法可以防止缓存未完成,就关闭serviceWorker
  event.waitUntil(
    //caches api: https://developer.mozilla.org/zh-CN/docs/Web/API/CacheStorage
    caches.open('v1').then(function(cache) {
      //指定要缓存的内容,地址为相对于跟域名的访问路径
      return cache.addAll([
        '/sw-test/',
        '/sw-test/index.html',
        '/sw-test/style.css',
        '/sw-test/app.js',
        '/sw-test/image-list.js',
        '/sw-test/star-wars-logo.jpg',
        '/sw-test/gallery/bountyHunters.jpg',
        '/sw-test/gallery/myLittleVader.jpg',
        '/sw-test/gallery/snowTroopers.jpg'
      ]);
    })
  );
});

//监听fetch,拦截请求
this.addEventListener('fetch', function(event) {
  var response;
  
    event.respondWith(
    caches.match(event.request).then(function(response) {
      if (response) {
        console.log('Found response in cache:', response);

        return response;
      }
      console.log('No response found in cache. About to fetch from network...');

      return fetch(event.request).then(function(response) {
        console.log('Response from network is:', response);
        caches.open('v1').then(function(cache) {
          cache.put(event.request, response);
        });
    		return response.clone();
        
      }).catch(function(error) {
        console.error('Fetching failed:', error);
        throw error;
      });
    })
  );
  
});


应用
  1. 缓存静态资源,Service Worker的一大应用是可以利用CacheStorage API来缓存js、css、字体、图片等静态文件。我们可以在Service Worker的install阶段,指定需要缓存的具体文件,在fetch事件的回调函数中,检查请求的url,如果匹配了已缓存的资源,则不再从服务端获取,以此达到提升网页性能的目的。
  2. 离线体验,将整个页面缓存下来,比如404页面。

详细见:Service Worker 从入门到出门

缓存的位置

缓存主要有4种:Service WorkerMemory CacheDisk CachePush Cache

  • Service Worker
  • Memory Cache,内存中的缓存,主要包含的是当前中页面中已经抓取到的资源(一般是小资源),例如页面上已经下载的样式、脚本、图片等,读取速度快,但是持续时间短,一般页面关闭就被释放。
  • Disk Cache,存储在硬盘中的缓存,能缓存各种资源,读取速度比内存慢,但是能缓存的数据多。
  • Push Cache,推送缓存是 HTTP/2 中的内容,当以上三种缓存都没有命中时,它才会被使用。它只在会话(Session)中存在,一旦会话结束就被释放。

刷新对于缓存的影响

  1. 当ctrl+f5强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存。
  2. 当f5刷新网页时,跳过强缓存,但是会检查协商缓存。
  3. 浏览器地址栏中写入URL,回车 浏览器发现缓存中有这个文件了,不用继续请求了,直接去缓存拿。

参考

Service Worker 从入门到出门
浏览器帧的会缓存一年吗

DNS 缓存

有DNS的地方,就有缓存。浏览器、操作系统、Local DNS、根域名服务器,它们都会对DNS结果做一定程度的缓存:

  • 首先查找浏览器自身的缓存
  • 然后是本机hosts,如果还是没有,则查找本地DNS服务器
  • 本地DNS服务器一般是动态分配的或者我们自己指定的地址(当然这里还有个路由器的缓存)
  • 再查找不到,则向根服务器发送递归查找,边缘DNS > 顶级DNS > 二级DNS > 三级DNS(也就是网站注册的)

CDN缓存

在浏览器本地缓存失效后,浏览器会向CDN边缘节点发起请求。类似浏览器缓存,CDN边缘节点也存在着一套缓存机制。CDN边缘节点缓存策略因服务商不同而不同,但一般都会遵循http标准协议,通过http响应头中的Cache-control判断资源是否过期
其优势是:

  1. CDN节点解决了跨运营商和跨地域访问的问题,访问延时大大降低。
  2. 大部分请求在CDN边缘节点完成,CDN起到了分流作用,减轻了源服务器的负载。
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值