认识浏览器的Service Worker

Post on Jun 30, 2017 by Lightfish Zhang

前言

初闻pwa,我简单了解下,简单理解为谷歌自定义规范的单页面应用。然后遭到友人的反驳,原来google chrome有Service Worker的大杀器,在于开发轻应用。
轻应用的好处,举个例子,为一些网络不好的地区,如东南亚等地,可能网络环境相当于国内的2G,下载庞大的app原生安装包不现实,使用轻应用就节省太多资源了。

认识chrome的Service Worker

服务工作线程是浏览器在后台独立于网页运行的脚本,它打开了通向不需要网页或用户交互的功能的大门。现在,它们已包括如推送通知和后台同步等功能。将来,服务工作线程将会支持如定期同步或地理围栏等其他功能。
在服务工作线程出现前,存在能够在网络上为用户提供离线体验的另一个 API,称为 AppCache。App Cache 的主要问题是,它具有相当多的缺陷,并且,虽然它对单页网络应用支持较好,但对多页网站来说则不尽人意。服务工作线程则能很好地避免这些常见的难点。

Service Worker可以做什么

  • 中文叫法是:服务工作线程
  • 它是一种 JavaScript 工作线程,无法直接访问 DOM。 服务工作线程通过响应 postMessage 接口发送的消息来与其控制的页面通信,页面可在必要时对 DOM 执行操作。
  • 服务工作线程是一种可编程网络代理,让您能够控制页面所发送网络请求的处理方式。
  • 使用服务工作线程,您可以劫持连接、编撰以及过滤响应。这是一个很强大的工具,处于安全考虑,浏览器限制在https协议的页面上注册服务工作线程

实例demo

注册Service

  • javascript代码如下,有注释
if ('serviceWorker' in navigator) { // 检查浏览器是否支持service worker
  window.addEventListener('load', function() {
      // 注册接口,注意sw.js路径,sw.js拥有所在目录以下的网域所有权,而不能作用上级目录
    navigator.serviceWorker.register('/sw.js').then(function(registration) {
      // Registration was successful
      console.log('ServiceWorker registration successful with scope: ', registration.scope);
    }).catch(function(err) {
      // registration failed :(
      console.log('ServiceWorker registration failed: ', err);
    });
  });
}

sw.js文件代码示例

  • 安装worker, 并缓存资源
var CACHE_NAME = 'my-site-cache-v1';
var urlsToCache = [
  '/',
  '/styles/main.css',
  '/script/main.js'
];

self.addEventListener('install', function(event) {
  // event.waitUntil() 方法带有 promise 参数并使用它来判断安装所花费的时间以及安装是否成功。
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});

//在安装服务工作线程且用户转至其他页面或刷新当前页面后,服务工作线程将开始接收 fetch 事件
self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(response) {
        // 命中缓存,就返回缓存的资源
        if (response) 
          return response;

        /*
        该响应是 Stream,因此主体只能使用一次。
        由于我们想要返回能被浏览器使用的响应,并将其传递到缓存以供使用,
        因此需要克隆一份副本。我们将一份发送给浏览器,另一份则保留在缓存。
        */
        var fetchRequest = event.request.clone();

        return fetch(fetchRequest).then(
          function(response) {
            if(!response || response.status !== 200 || response.type !== 'basic')
              return response;
            var responseToCache = response.clone();
            caches.open(CACHE_NAME)
              .then(function(cache) {
                cache.put(event.request, responseToCache);
              });
            return response;
          }
        );
      })
    );
});

Service Worker使用场景

  • 省流量
  • 可以使用js判断当前设备的分辨率,响应与缓存相应的像素大小的图片,提高响应效率

progressive web apps

  • Service Worker还有更多的功能,比如可以开发chrome上的轻应用,如安卓手机上,可以添加网页应用的图标,点击打开就是一个无浏览器边框的web app,具体参考本文附录资料

资源收集