Service Worker简介

介绍

Service Workder相当于浏览器与web应用程序之间的代理服务器,可以捕获请求事件并做相应处理;目前主要用于离线应用以及消息推送及后台同步等;

特性

  1. 无法直接访问和操作DOM
  2. 在长时间不用时会被中止并在下次需要时重启;
  3. 可以访问和操作indexedDB API
  4. 推荐使用HTTPS
  5. 内部实现基于Promise

生命周期

  1. install事件是SW的第一个事件,只会发生一次,使用e.waitUtil()监测是否安装成功;
  2. 生命周期中的主要围绕两个事件installactivateinstall前后的生命周期包括installinginstalledactivate前后的生命周期包括activatingactivated;最后SW不用或者新旧更替时经历的生命周期时redundant
  3. 在安装成功并处于活动状态之前,不会处理functional events
  4. 处于activated状态才可以处理functional events: fetch/push/sync

Service Worker简介_第1张图片

支持的事件

Service Worker简介_第2张图片

使用

demo地址

  1. 注册
    可以通过serviceWorker.register()方法注册一个Service Worker实例,它是由Promise实现的,resolve后在then函数中拿到registration对象;包含了所注册sw的相关信息,如下图:

    Service Worker简介_第3张图片

    具体注册实现的过程如下图:

    if ('serviceWorker' in navigator) {
        window.addEventListener('load', () => {
            navigator.serviceWorker.register('sw.js')
            .then(registration => {
                console.log('sw installed: ', registration);
            })
            .catch(err => console.log('sw installed failed: ', err))
        })
    }
    
    
  2. 安装 Service Worker
    在本文生命周期一节中,根据图示我们看到install事件中可以通过event.waitUntil()方法建立一个Promise对象来等待安装完成,安装完成后则Promiseresolve,然后我们可以打开缓存并存缓存需要缓存的资源;

    具体实现如下:

    var CACHE_NAME = 'sw-cache';
    var CACHE_URLS = ['./index.html', './index.js', './public/equal.png', './public/icon.png'];
    self.addEventListener('install', e => {
    	e.waitUntil(
    		caches.open(CACHE_NAME)		// 打开缓存
    		.then(cache => cache.addAll(CACHE_URLS))
    	)
    }
    
  3. 捕获请求并处理

    具体实现如下:

    self.addEventListener('fetch', e => {
    	e.respondWith(
    		caches.match(e.request)	// 检测缓存资源和请求资源是否匹配, e.request具有以下属性:url/method/header/body
    		.then(res => {
    			if (res) {
    				return res;
    			}
    			console.log('loaded from sw');
    		})
    	)
    })
    
  4. 更新

    1. 自动更新
      Service Workder的更新遵循以下步骤(来自谷歌开发者):

      1. 更新您的服务工作线程 JavaScript 文件。 用户导航至您的站点时,浏览器会尝试在后台重新下载定义 Service Worker 的脚本文件。 如果 Service Worker 文件与其当前所用文件存在字节差异,则将其视为新 Service Worker。
      2. 新 Service Worker 将会启动,且将会触发 install 事件。
      3. 此时,旧 Service Worker 仍控制着当前页面,因此新 Service Worker 将进入 waiting 状态。
      4. 当网站上当前打开的页面关闭时,旧 Service Worker 将会被终止,新 Service Worker 将会取得控制权。
      5. 新 Service Worker 取得控制权后,将会触发其 activate 事件。

      下图可以看到:当我们更新了sw.js文件后,新的sw处于waiting to active的状态,而旧的sw仍然运行并且处于active状态;
      Service Worker简介_第4张图片

      关闭上图中的标签页http://127.0.0.1:5500/service%20worker/index.html并重新打开页面后:如下图,我们可以看到新的id为128的sw已经运行并处于active状态;
      Service Worker简介_第5张图片
      当然,可以通过调用self.skipWaiting()跳过等待阶段,在安装完成后立即激活;

    2. 手动更新

      navigator.serviceWorker.register('/sw.js').then(reg => {
      	// something later
      	reg.update();
      })
      
  5. 删除旧缓存
    由于浏览器对Service Worker可用的磁盘空间有严格限制,因此更新Service Worker时,我们需要进行缓存管理;
    根据Service Worker的生命周期,我们可以看到在active阶段Service Worker处于活跃状态,即可以管理旧sw相关的资源;

    self.addEventListener('activate', function(event) {
    	// 建立需要保存的缓存白名单
      var cacheWhitelist = ['pages-cache-v1', 'blog-posts-cache-v1'];
    
      event.waitUntil(
        caches.keys().then(function(cacheNames) {
          return Promise.all(
            cacheNames.map(function(cacheName) {
              if (cacheWhitelist.indexOf(cacheName) === -1) {
                return caches.delete(cacheName);
              }
            })
          );
        })
      );
    });
    

效果演示

Service Worker简介_第6张图片

参考文献:

  1. https://developers.google.com/web/fundamentals/primers/service-workers/?hl=zh-CN
  2. https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_API/Using_Service_Workers
  3. https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle?hl=zh-CN

你可能感兴趣的:(web前端,新兴技术)