ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

浅谈 Service Worker 在缓存资源以及Web Push上的应用

2020-12-29 16:00:17  阅读:237  来源: 互联网

标签:function Web 缓存 console 浅谈 Service worker serviceWorker event


一、 service worker 是什么

一句话概括

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

细碎的描述

  • 基于web worker(一个独立于JavaScript主线程的独立线程,在里面执行需要消耗大量资源的操作不会堵塞主线程)
  • web worker的基础上增加了离线缓存的能力
  • 本质上充当Web应用程序(服务器)与浏览器之间的代理服务器(可以拦截全站的请求,并作出相应的动作->由开发者指定的动作)
  • 创建有效的离线体验(将一些不常更新的内容缓存在浏览器,提高访问体验)
  • 由事件驱动的,具有生命周期
  • 可以访问cacheindexDB
  • 支持推送
  • 并且可以让开发者自己控制管理缓存的内容以及版本

本篇文章主要在缓存推送上对ServiceWorker进行分析。

二、 使用Service Worker 缓存资源

注册Service worker 在你的index-service-worker.html加入以下内容

/* 判断当前浏览器是否支持serviceWorker */
    if ('serviceWorker' in navigator) {
        /* 当页面加载完成就创建一个serviceWorker */
        window.addEventListener('load', function () {
            /* 创建并指定对应的执行内容 */
            /* scope 参数是可选的,可以用来指定你想让 service worker 控制的内容的子目录。 在这个例子里,我们指定了 '/',表示 根网域下的所有内容。这也是默认值。 */
            navigator.serviceWorker.register('./serviceWorker.js', {scope: './'})
                .then(function (registration) {
 
                    console.log('ServiceWorker registration successful with scope: ', registration.scope);
                })
                .catch(function (err) {
 
                    console.log('ServiceWorker registration failed: ', err);
                });
        });
    }

安装worker:在我们指定的处理程序serviceWorker.js中书写对应的安装及拦截逻辑

/* 监听安装事件,install 事件一般是被用来设置你的浏览器的离线缓存逻辑 */
this.addEventListener('install', function (event) {
 	console.log('worker installed')
    /* 通过这个方法可以防止缓存未完成,就关闭serviceWorker */
    event.waitUntil(
        /* 创建一个名叫V1的缓存版本 */
        caches.open('v1').then(function (cache) {
            /* 指定要缓存的内容,地址为相对于跟域名的访问路径 */
            return cache.addAll([
                './index-service-worker.html'
            ]);
        })
    );
    /* 注册fetch事件,拦截全站的请求 */
	this.addEventListener('fetch', function(event) {
	  event.respondWith(
	    // magic goes here
	      
	     /* 在缓存中匹配对应请求资源直接返回 */
	    caches.match(event.request)
	  );
	});
});


部署测试:

html页面必须部署在服务器上运行,所以建议使用iis本地搭建一个服务器。具体步骤不在详述,自行百度即可。运行效果如下:

在这里插入图片描述

然后打开 谷歌浏览器 application 栏,可以找到serviceWorker已经被成功加载

在这里插入图片描述
serviceWorker一旦被加载,如果serviceWorker文件没有变化,则不会再次被安装,会像localstorage一样缓存在网站中。手动卸载serviceWorker可以点击Unregister,这样再次刷新页面,serviceWorker会被重新加载。

在这里插入图片描述
接下来我们添加一张网页图片,注意,这时候我是用iis新建了一个网站 8002端口。在8001网站加载这个图片,并且把这个图片添加到ServiceWorker.js的缓存目录中:

/* 监听安装事件,install 事件一般是被用来设置你的浏览器的离线缓存逻辑 */
this.addEventListener('install', function (event) {
    console.log('worker installed')
    /* 通过这个方法可以防止缓存未完成,就关闭serviceWorker */
    event.waitUntil(
        /* 创建一个名叫V1的缓存版本 */
        caches.open('v1').then(function (cache) {
            /* 指定要缓存的内容,地址为相对于跟域名的访问路径 */
            return cache.addAll([
                './index-service-worker.html',
                'http://localhost:8002/testimage.png'
            ]);
        })
    );
});

这里我们为了试验效果,排除浏览器本身缓存(disk cachememory cache)的影响,先禁用浏览器缓存:
在这里插入图片描述
我们部署完毕图片之后,刷新页面,看到由于我们修改了ServiceWorker文件内容,浏览器重新加载了我们的ServiceWorker:
在这里插入图片描述

刷新页面,查看testimage.png和的加载方式,发现是来自ServiceWorker:

在这里插入图片描述
这时我们断开8002端口的服务器:发现图片仍然可以正常显示:

在这里插入图片描述

三、使用Service Worker 推送服务器消息

Service Worker发送Push(Notification)或者叫web pushWeb push在国外的网站很流行,但在国内几乎没见到,主要还是因为谷歌在境内无法访问,因为web push走的是谷歌FCM通道,需要能接收到谷歌服务器的消息。但正常网络环境下是无法访问谷歌的,如果需要正常访问需要对应的服务端服务器运行在可以访问到谷歌的网络服务器上。

在这里插入图片描述
这里由于应用范围不广,服务器端的推送流程我们就不说了,也不好模拟。客户端调试器中有推送消息的测试接口,我们正好可以拿来测试。

客户端添加监听

this.addEventListener('push', function (event) {
    console.log('[Service Worker] Push Received.');
    console.log(event.data)
    console.log(`[Service Worker] Push had this data: "${event.data.text()}"`);

    event.waitUntil(self.registration.showNotification('提示信息test', {
         body: event.data.text(),
         icon: './images/logo/logo152.png',
    }));
    event.data.text()
});

打开F12 Application 找到我们的Worker,发送推送消息

在这里插入图片描述
首先控制台报了一个错:
在这里插入图片描述
很明显,浏览器推送需要用户授权才可以。这个跟目前的主流手机操作系统保持一致,避免频繁的弹窗,我们需要在用户注册完WebWorker之后,申请用户的授权:

 if ('serviceWorker' in navigator) {
        /* 当页面加载完成就创建一个serviceWorker */
         window.addEventListener('load', function () {
             /* 创建并指定对应的执行内容 */
             /* scope 参数是可选的,可以用来指定你想让 service worker 控制的内容的子目录。 在这个例子里,我们指定了 '/',表示 根网域下的所有内容。这也是默认值。 */
             navigator.serviceWorker.register('./serviceWorker.js', { scope: './' })
                 .then(function (registration) {
                     if (window.PushManager) {
                         registration.pushManager.getSubscription().then(subscription => {
                             // 如果用户没有订阅
                             if (!subscription) {
                                 subscribeUser(registration);
                             } else {
                                 console.log("You have subscribed our notification");
                             }       
                         });     
                     }
                     console.log('ServiceWorker registration successful with scope: ', registration.scope);
                 })
                 .catch(function (err) {

                     console.log('ServiceWorker registration failed: ', err);
                 });
         });
     }

subscribeUser 方法如下:

function subscribeUser(swRegistration) {
            const applicationServerPublicKey = "BBlY_5OeDkp2zl_Hx9jFxymKyK4kQKZdzoCoe0L5RqpiV2eK0t4zx-d3JPHlISZ0P1nQdSZsxuA5SRlDB0MZWLw";
            const applicationServerKey = base64ToUint8Array(applicationServerPublicKey);
            swRegistration.pushManager.subscribe({
                userVisibleOnly: true,
                applicationServerKey: applicationServerKey
            })
            // 用户同意
            .then(function(subscription) {
                console.log('User is subscribed:', JSON.stringify(subscription));
                //--向服务器注册当前订阅
            })
            // 用户不同意或者生成失败
            .catch(function(err) {
                console.log('Failed to subscribe the user: ', err);
            });
        }

完成之后,刷新页面,出现如下提示。点击允许。
在这里插入图片描述
我们再次尝试用控制台推送:果然出现了如下提示信息。
在这里插入图片描述
以上过程只是用最简单的方式实现了客户端推送,生成公钥和私钥的过程都进行了忽略,且省略了服务器部分对这里的处理。有关服务器部分的订阅以及推送逻辑,可以参考这篇文章

四、结语

Service Worker让我们在Web端也能有像原生APP一样的Push通知,使得Web端越来越像原生APP端,随着HTML5的其它新功能如WebAssembly提高运行速度,WebWorker多线程支持,数据库支持大量数据的管理和支持,Websocket进行实时通信,WebRTC进行P2P多媒体传输,还有WebGL、新进的WebVR等,使得在浏览器端能够做的事情越来越多,体验越来越丰富,而且这种Web APP还是跨平台的。Web技术日新月异的发展,让我们相信Web有搞头。

标签:function,Web,缓存,console,浅谈,Service,worker,serviceWorker,event
来源: https://blog.csdn.net/qq_29722281/article/details/111873764

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有