美文网首页
了解service worker

了解service worker

作者: 菜菜的小阿允 | 来源:发表于2020-12-10 16:32 被阅读0次

前端开发者简历中经常会写熟悉HTML5,但是面试中一问service worker的内容,就容易翻车,现在就来总结一下。

简介

W3C组织早在2014年5月就提出过Service Worker这样的一个HTML5 API ,主要用来做持久的离线缓存。
浏览器中js运行在单一主线程中,同一时间只能做一件事情。 如果一段代码运算太过耗时,就会一直占用浏览器主线程,造成性能下降。基于这个问题,W3C提出了web Worker,将耗时太长的任务交给web worker,然后通过post Message告诉主线程,主线程通过onMessage得到结果。但是web Worker是临时的,每次运行的结果不能持久的保持下来,下次有复杂的运算,还需要重新计算一次。为了解决这个问题,推出了Service Worker,相对于web worker增加了离线缓存能力。
Service Worker是一个事件驱动worker,运行在一个单独的后台进程,是PWA(ProgressiveWeb App)运行的基础。主要用于代理网页请求,可缓存请求结果;可实现离线缓存功能,也拥有单独的作用域范围和运行环境。我们以后把Service Worker简称为SW。

SW使用限制和主要作用
  • 使用限制:SW除了work线程的限制外,由于可拦截页面请求,为了保证页面安全,浏览器端对sw的使用限制也不少。
    1、无法直接操作DOM对象,也无法访问window、document、parent对象。可以访问navigator、location; SW 通过响应 postMessage 接口发送的消息来与其控制的页面通信,页面可在必要时对 DOM 执行操作。
    2、可代理的页面作用域限制。默认是sw.js所在文件目录及子目录的请求可代理,可在注册时手动设置作用域范围;
    3、必须在 https 中使用,允许在开发调试的localhost使用。
  • SW主要作用
    1、可以用来做缓存,以达到提升体验、节省浏览等等
    2、SW 是一种可编程网络代理,让您能够控制页面所发送网络请求的处理方式。
    3、离线缓存接口请求及文件,更新、清除缓存内容;
    4、可分配给 Service Worker 一些任务,并在使用基于 Promise 的方法当任务完成时收到结果。
    5、Service Worker处于空闲状态会被终止,在下一次需要时重启。
SW的生命周期

SW 的生命周期完全独立于网页。SW为网页添加一个类似于 App 的生命周期,它只会响应系统事件,就算浏览器关闭时操作系统也可以唤醒 SW,这点非常重要,让Web App与 Native App 的能力变得类似了。由于是离线缓存,所以在初始安装时、更新它们的所走的生命周期是不相同。下面我们就以初始安装时结合代码来分析它的执行步骤。
SW的生命周期大致分为:注册、更新、安装成功、安装失败、激活、销毁。

SW的使用
  • 使用SW前提条件
    1、必须在 https 中使用,允许在开发调试的localhost使用。
    2、浏览器必须支持SW
  • 初始安装时:大致可以分为注册SW => 安装SW => 激活 => 空闲 => (缓存和返回请求/终止),在初始安装时会大致分为这几个步骤,下面就按照这几个步结合代码实现。流程图如下:



    1、注册 Service Worker
    用户首次访问SW控制的网站或页面时,sw.js会立刻被下载和解析。我们要在页面中写入JavaScript来注册SW。

    // 判断浏览器是否支持serviceWorker
    // 首先检浏览器是否支持SW,如果支持就在浏览器加载后通过register().then注册sw.js,并且设置注册成功或者失败的回调函数。
    if ('serviceWorker' in navigator) {
        // 在页面加载后
        window.addEventListener('load', function () {
            // 通过navigator.serviceWorker.register 注册'./sw.js
            navigator.serviceWorker.register('./sw.js')
            .then(reg => { //注册成功
                console.log('注册成功', reg)
            }).catch(err => { //注册成功
                console.log('注册失败', err)
            })
        });
    } else {
        console.log('当前浏览器不支持SW')
    }

2、安装 Service Worker
在受控页面启动注册流程后,下面就是SW获取的第一个事件install,并且只发生一次。传递到 installEvent.waitUntil() 的一个 promise 可表明安装的持续时间以及安装是否成功。在install中要做三件事打开缓存、缓存文件、确认所有需要的资产是否已缓存。

    // 在sw.js中监听对应的安装事件,并预处理需要缓存的文件
    // 该部分内容涉及到cacheStorage API

    // 定义缓存空间名称
    const CACHE_NAME = 'sw_cache_v1';
    // 定义需要缓存的文件目录
    let cachelist = ['./app.js', './index.css'];
    // 监听安装事件,返回installEvent对象
    self.addEventListener('install', function (installEvent) {
        // waitUntil方法执行缓存方法
        installEvent.waitUntil(
            // cacheStorage API 可直接用caches来替代
            // open方法创建/打开缓存空间,并会返回promise实例
            // then来接收返回的cache对象索引
            caches.open(CACHE_NAME)
             // cache对象addAll方法解析(同fetch)并缓存所有的文件
            .then(function(cache) {
                console.log('Opened cache');
                return cache.addAll(cachelist);
            })
        );
    });

3、激活
SW 准备控制客户端并处理 push 和 sync 等功能事件时,您将获得一个 activate 事件。但这不意味着调用 .register() 的页面将受控制。如果第二次加载此演示(换言之,刷新页面),该页面将受控制。改写代码sw.js如下:

    self.addEventListener('install', () => {
        // 一般注册以后,激活需要等到再次刷新页面后再激活
        // 可防止出现等待的情况,这意味着服务工作线程在安装完后立即激活
        self.skipWaiting();
    })
    self.addEventListener('activate', function (event) {
        event.waitUntil(
            // cacheStorage API 可直接用caches来替代
            // open方法创建/打开缓存空间,并会返回promise实例
            // then来接收返回的cache对象索引
            caches.open(CACHE_NAME)
            // cache对象addAll方法解析(同fetch)并缓存所有的文件
            .then(function(cache) {
                console.log('Opened cache');
                return cache.addAll(cachelist);
            })
        );
    })

4、clients.claim
激活 SW 后,您可以通过在其中调用 clients.claim() 控制未受控制的客户端。google developer中的一个异步加载图片的实例。下面修改代码如下:

    self.addEventListener('install', (event) => {
        event.waitUntil(
            // cacheStorage API 可直接用caches来替代
            // open方法创建/打开缓存空间,并会返回promise实例
            // then来接收返回的cache对象索引
            caches.open(CACHE_NAME)
            // cache对象addAll方法解析(同fetch)并缓存所有的文件
            .then(function(cache) {
                console.log('Opened cache');
                return cache.addAll(cachelist);
            })
        );
        // 一般注册以后,激活需要等到再次刷新页面后再激活
        // 可防止出现等待的情况,这意味着服务工作线程在安装完后立即激活
        self.skipWaiting();
    })
    self.addEventListener('activate', function (event) {
        // 若缓存数据更改,则在这里更新缓存
        var cacheDeletePromise = caches.keys()
        .then(keyList => {
            Promise.all(keyList.map(key => {
                if (key !== CACHE_NAME) {
                    var deletePromise = caches.delete(key)
                    return deletePromise
                } else {
                    Promise.resolve()
                }
            }));
        });
        event.waitUntil(
            Promise.all([cacheDeletePromise]).then(res => {
                this.clients.claim()
            })
        );
    })

5、缓存和返回请求
上我们已经安装并且激活了SW,现在我们要返回一个缓存的响应。SW用户转至其他页面或刷新当前页面后,将开始接受fetch事件。

    self.addEventListener('fetch', function(event) {
        event.respondWith(
            caches.match(event.request)
            .then(function(response) {
                // Cache hit - return response
                if (response) {
                    return response;
                }
                return fetch(event.request);
            })
        );
    });

相关文章

网友评论

      本文标题:了解service worker

      本文链接:https://www.haomeiwen.com/subject/drslgktx.html