[译]前端离线指南(上)

原文链接:
The offline cookbook

作者:Jake Archibald

运用AppCache可以为我们供应几种支撑内容离线事情的情势。假如这些情势恰是你所需要的,那末祝贺你,你中了APPCache的大奖(只管头等奖依旧无人认领),但我们这些其他的人都挤在角落里往返摇晃(译者注:作者指的是由于设想上的缘由,AppCache逐渐地被Web规范移除,虽然如今依旧有浏览器支撑这个功用,但最好不要再运用它了)

关于ServiceWorker(引见),我们摒弃尝试去处置惩罚离线题目,而且给开发者们供应天真的组件从而让他们本身去处置惩罚离线题目。它为您供应了掌握缓存和处置惩罚要求的体式格局。这就意味着您可以建立您本身的情势。接下来让我们来看一下几个断绝环境下的可行情势,然则在实践中,您能够会依据URL和context以串连体式格局用到个中的多个情势。

现在,除非尚有申明,一切的示例代码都可以运转在Chrome和Firefox浏览器中。关于ServiceWorker支撑水平的完整概况,请查阅“Is Service Worker Ready?”

有关关于个中部份情势的运转演示,请查阅Trained-to-thrill,而且此处的视频将向您展现机能影响。

缓存机-什么时刻最先存储资本?

您可以经由过程ServiceWorker来独登时从缓存中处置惩罚要求,所以我们要先单独地研究一下它们。起首,我们啥时刻应当举行缓存呢?

装置时——以依靠的情势

《[译]前端离线指南(上)》

ServiceWorker供应给您一个install事宜,您可以运用它把资本准备好,即在处置惩罚其他事宜之前必需要提早准备好的东西。然则当这些操纵正在举行中的时刻,任何旧版本的ServiceWorker仍旧在运转而且供应给页面,因而您在此处举行的操纵肯定不能中缀它们。

适用于: CSS、图片、字体、JS文件、模板等,基础包含了你以为网站在当前“版本”中应当需要的一切静态资本。

假如未能猎取上述资本,那末您的网站完整没法运转,对应的本机运用会将这些对象包含在初始下载中。

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open('mysite-static-v3').then(function(cache) {
      return cache.addAll([
        '/css/whatever-v3.css',
        '/css/imgs/sprites-v6.png',
        '/css/fonts/whatever-v8.woff',
        '/js/all-min-v4.js'
        // etc
      ]);
    })
  );
});

event.waitUntil接收一个promise对象作参数,来定义装置时长和装置是不是胜利,假如promise状况为rejected,则以为此次装置失利,而且扬弃ServiceWorker(假如一个旧版本的ServiceWorker正在运转,则它将坚持稳固)。caches.opencaches.addAll都返回promise对象,假如个中有任何一个资本猎取失利,则caches.addAll会挪用reject。
trained-to-thrill 上,我运用此要领缓存静态资本

装置时——不作为依靠

《[译]前端离线指南(上)》

此体式格局与上述相似,但区别是:纵然缓存失利,既不会耽误装置也不会致使装置失利。

适用于: 体积较大的,且临时用不到的资本,比方用于游戏的较高级别的资本。

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open('mygame-core-v1').then(function(cache) {
      cache.addAll(
        // levels 11-20
      );
      return cache.addAll(
        // core assets & levels 1-10
      );
    })
  );
});

我们没有将levels 11-20的cache.addAll promise对象,返回给event.waitUntil,所以事宜纵然失利,游戏在离线的时刻依旧可以运用。固然,您必需考虑到缺乏这些level的状况,假如缺乏它们,则尝试从新缓存它们。

在当level 11-20正在下载的时刻,ServiceWorker能够会停止,由于它已完成处置惩罚事宜。这就意味着它们就不会被缓存下来。将来,我们设计增加一个在背景下载的API以处置惩罚相似如许的状况,以及下载像影戏一样的大体积文件。

激活时

适用于: 清算和迁徙

《[译]前端离线指南(上)》

在新的ServiceWorker已被装置,而且较早版本的sw没有在运用的状况下,则新的ServiceWorker会被激活,您就会获得一个activate事宜。由于旧版本的退出,所以此时异常合适处置惩罚 IndexedDB 中的架构迁徙和删除未运用的缓存。

self.addEventListener('activate', function(event) {
  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.filter(function(cacheName) {
          // 假如您想删除缓存,则返回true,
          // 然则请记着缓存在该域名内的一切页面之间
          // 是同享的
        }).map(function(cacheName) {
          return caches.delete(cacheName);
        })
      );
    })
  );
});

在激活的过程当中,诸如fetch等事宜会被安排在一个行列中,所以一个长时候的激活能够会壅塞页面加载。保证您的激活尽量地简约,仅用于旧版本处于运动状况时没法实行的操纵。

trained-to-thrill上,我运用此要领移除旧缓存

在用户交互时

《[译]前端离线指南(上)》

适用于: 假如全部站点没法离线事情,您可以许可用户挑选需要离线的可用内容,比方,YouTube上的某个视频,维基百科上的某篇文章,Flickr上的某张图片等等。

为用户供应一个“稍后浏览”或许“离线保留”的按钮。当点击按钮,从收集中猎取您所需要的内容并把它放进缓存中。

document.querySelector('.cache-article').addEventListener('click', function(event) {
  event.preventDefault();

  var id = this.dataset.articleId;
  caches.open('mysite-article-' + id).then(function(cache) {
    fetch('/get-article-urls?id=' + id).then(function(response) {
      // /get-article-urls returns a JSON-encoded array of
      // resource URLs that a given article depends on
      return response.json();
    }).then(function(urls) {
      cache.addAll(urls);
    });
  });
});

cacheAPI在页面既可以在ServiceWorker中猎取到,也可以在页面中猎取到,这就意味着你没必要肯定要经由过程ServiceWorker来向缓存中增加内容。

收集相应时

《[译]前端离线指南(上)》

适用于: 频仍更新的资本,比方用户收件箱,或许文章内容。一样适用于不重要但需要郑重处置惩罚的内容,比方用户头像。

假如要求的资本与缓存中的任何资本均不婚配,则从收集中猎取,将其发送到页面中,同时将其增加到缓存中。

假如您针对一系列网址实行此操纵,如头像,那末您需要郑重,不要使域名下的存储变得痴肥,假如用户需要接纳磁盘空间,您不会想成为重要候选对象。请确保将缓存中不再需要的项目删除。

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.open('mysite-dynamic').then(function(cache) {
      return cache.match(event.request).then(function (response) {
        return response || fetch(event.request).then(function(response) {
          cache.put(event.request, response.clone());
          return response;
        });
      });
    })
  );
});

为了高效运用内存,只许可读取一次responserequestbody,在上面的代码中,运用.clone来建立可以单独地读取数据的分外副本。

trained-to-thrill上,我运用此要领缓存Flickr图象

Stale-while-revalidate

《[译]前端离线指南(上)》

适用于: 频仍更新,但却没必要猎取最新的资本。用户头像就属于此类。

假如缓存中已有一个可用的版本,直接运用该版本,然则会为了下一次的要求而猎取一个更新版本。

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.open('mysite-dynamic').then(function(cache) {
      return cache.match(event.request).then(function(response) {
        var fetchPromise = fetch(event.request).then(function(networkResponse) {
          cache.put(event.request, networkResponse.clone());
          return networkResponse;
        })
        return response || fetchPromise;
      })
    })
  );
});

它和 HTTP 的 stale-while-revalidate 异常相似。

推送音讯时

《[译]前端离线指南(上)》

注重: Chrome临时还不支撑Push。(译者注:Chrome 50及以后的版本最先支撑,更多信息请参考 can i use

Push API是基于ServiceWorker构建的另一个功用。它许可叫醒ServiceWorker以相应来自体系效劳的音讯,即运用户没有为您的站点翻开一个标签,Push API也一样可以事情。只要ServiceWorker被叫醒。您从页面要求实行此操纵权限的同时,用户也将收到提醒。

适用于: 与关照有关的内容,比方谈天音讯,突发消息,或许Email等。一样适用于不常常变动的可马上同步的内容,比方待办事项更新或许日程表的变动。

用户罕见的页面表现是,涌现一个关照,当点击它的时刻,会翻开或许聚焦到相干的页面,然则在点击它之前,务必要更新缓存。明显,用户在收到推送音讯的时刻,肯定是在线的,然则,当他们终究与关照交互时能够已离线,因而,许可离线接见此内容异常重要。Twitter原生运用在大多数状况下都是异常好的离线优先例子,但在这点上却有点小题目。

假如没有收集连接,Twitter没法供应与推送音讯相干的内容。然则点按关照会移除通,从而运用户猎取的信息比点按关照之前还要少。不要这么做!

下面的代码会在展现关照之前更新缓存。

self.addEventListener('push', (event) => {
  if (event.data.text() == 'new-email') {
    event.waitUntil(async function() {
      const cache = await caches.open('mysite-dynamic');
      const response = await fetch('/inbox.json');
      await cache.put('/inbox.json', response.clone());
      const emails = await response.json();
      registration.showNotification("New email", {
        body: "From " + emails[0].from.name
        tag: "new-email"
      });
    }());
  }
});

self.addEventListener('notificationclick', function(event) {
  if (event.notification.tag == 'new-email') {
    // Assume that all of the resources needed to render
    // /inbox/ have previously been cached, e.g. as part
    // of the install handler.
    new WindowClient('/inbox/');
  }
});

背景同步时

《[译]前端离线指南(上)》

注重: 背景同步还没有加入到Chrome稳固版本中。(译者注:Chrome 49及以后的版本中最先支撑,但FireFox、Safari还没有支撑,更多信息请参考 can i use

背景同步是基于ServiceWorker来构建的另一个功用。它许可您一次性地,或许根据(异常具有启发性的)时候距离来要求背景数据同步。即运用户没有为您的站点翻开一个标签,背景同步也一样可以事情。只要ServiceWorker被叫醒。您从页面要求实行此操纵权限的同时,用户也将收到提醒。

适用于: 不紧要的更新,尤其是那些按期举行的更新,每次更新都发送一个推送音讯显得太频仍,比方交际时候表和消息资讯。

    原文作者:司楠
    原文地址: https://segmentfault.com/a/1190000017268426
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞