第一次知道service worker是在面试题中看到的,但是当时由于深恶痛绝八股文,只是把service worker看做一道面试题而已。想深入了解service worker的原因是小程序的框架是双线程的,那为什么小程序会比浏览器渲染网页多一个线程? 小程序的逻辑层到底是怎么实现? 于是上mdn学习一下service worker。强烈建议想学习service worker的同学们上mdn去看,真的很详细,本文也主要是摘抄mdn上的内容。
小程序开发框架的逻辑层使用
JavaScript引擎为小程序提供开发JavaScript代码的运行环境以及微信小程序的特有功能。逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。
开发者写的所有代码最终将会打包成一份
JavaScript文件,并在小程序启动的时候运行,直到小程序销毁。这一行为类似 ServiceWorker,所以逻辑层也称之为 App Service。
1. 什么是service worker
Service worker 本质上充当 Web 应用程序、浏览器与网络(可用时)之间的代理服务器。这个 API 旨在创建有效的离线体验,它会拦截网络请求并根据网络是否可用来采取适当的动作、更新来自服务器的资源。它还提供入口以推送通知和访问后台同步 API。
Service worker 运行在 worker 上下文:因此它无法访问 DOM,相对于驱动应用的主 JavaScript 线程,它运行在其他线程中,所以不会造成阻塞。
出于安全考量,Service worker 只能由 HTTPS 承载,毕竟修改网络请求的能力暴露给中间人攻击会非常危险,如果允许访问这些强大的 API,此类攻击将会变得很严重。
中间人攻击(Man-in-the-middle attack,MitM)会在消息发出方和接收方之间拦截双方通讯。举例来说,Wi-Fi 路由器就可以被破解用来进行中间人攻击。
2. service worker能干什么
-
后台数据同步
-
响应来自其他源的资源请求
-
集中接收计算成本高的数据更新,比如地理位置和陀螺仪信息,这样多个页面就可以利用同一组数据
-
在客户端进行 CoffeeScript、LESS、CJS/AMD 等模块编译和依赖管理(用于开发目的)
-
后台服务钩子
-
自定义模板用于特定 URL 模式
-
性能增强,比如预取用户可能需要的资源,比如相册中的后面数张图片 未来 service worker 能够用来做更多使 web 平台接近原生应用的事。值得关注的是,其他标准也能并且将会使用 service worker,例如:
-
后台同步:启动一个 service worker 即使没有用户访问特定站点,也可以更新缓存
-
响应推送:启动一个 service worker 向用户发送一条信息通知新的内容可用
-
对时间或日期作出响应
-
进入地理围栏
我个人的话会对其实对响应推送比较感兴趣,因为之前在项目要实现服务器向前端推送消息的需求。当时并不是使用 PUSH API实现的。在此链接我的另一篇文章,介绍了一下目前能实现服务器向前端推送消息的技术方案。juejin.cn/editor/draf…
3. service worker的工作的基本过程
通常遵循以下基本步骤来使用 service worker:
- 获取 service worker 代码,然后使用
serviceWorkerContainer.register()来注册。如果成功,service worker 将在ServiceWorkerGlobalScope中执行;这本质上是一种特殊的上下文,在主脚本执行线程之外运行,没有访问 DOM 的权限。Service Worker 现在已为处理事件做好准备。 - 安装完成。
install事件始终是发送给 service worker 的第一个事件(这可用于启动填充 IndexedDB 和缓存站点资源的过程)。在此步骤期间,应用程序正在为离线可用做准备。 - 当
install程序处理完成时,service worker 被视为已安装。此时,service worker 的先前版本可能处于激活的状态并控制着打开的页面。由于我们不希望同一 service worker 的两个不同版本同时运行,因此新版本尚未激活。 - 一旦 service worker 的旧版本控制的页面都已关闭,就可以安全地停用旧版本,并且新安装的 service worker 将收到
activate事件。activate的主要用途是去清理 service worker 之前版本使用的资源。新的 service worker 可以调用skipWaiting()要求立即激活,而无需要求打开的页面关闭。然后,新的 service worker 将立即收到activate事件,并将接管任何打开的页面。 - 激活后,service worker 将立即控制页面,但是只会控制那些在
register()成功后打开的页面。换句话说,文档必须重新加载才能真正的受到控制,因为文档在有或者没有 service worker 的情况下开始存在,并在其生命周期内维护它。为了覆盖此默认行为并在页面打开的情况下,service worker 可以调用clients.claim()方法。 - 每当获取新版本的 service worker 时,都会再次发生此循环,并
在新版本的激活期间清理上一个版本的残留。
以下是可用的 service worker 主要监听的一些事件: