去年apple在iOS11.3的正式更新中,添加了对service worker的支持。新的桌面版Safari会默认打开Service Worker。这意味着我们可以通过Safari将支持PWA的站点像原生app一样添加到桌面,并且支持在离线状态下访问。至此,Microsoft, Chrome, Apple这些浏览器大厂都已全部支持了PWA。本文将为大家介绍PWA的特点、技术核心、创建方法、在项目中的应用和调试技巧。
PWA(progressing web app),渐进式网页应用程序,是google在2016年GoogleI/O大会上提出的下一代web应用模型,并在随后的日子里迅速发展。PWA的目的在于增强web体验。从功能上来讲,PWA首先是一个web应用,通过manifest.json配置文件以及Service Worker来获得web加载速度提升,支持离线工作,可被添加主屏幕,全屏执行等特性。这些特性使得web应用(尤其是移动设备)体验渐进式接近原生app。
在我们思考PWA会为我们带来哪些提升的时候,google已经为我们总结出了PWA的相关特性(可参考:https://developers.google.com/web/progressive-web-apps/)。
PWA会为web应用带来如下的特点:
Reliable – Load instantly and never show the downasaur, even in uncertainnetwork conditions(可靠的,即使在网络不稳定的条件下,也能够立即加载并且永远不会显示网络瘫痪的页面)
Fast – Respondquickly to user interactions with silky smooth animations and no jankyscrolling.(迅速的,借助于流畅的动画和无卡顿滚动实现快速响应用户的交互)
Engaging– Feel like a natural app on the device, with an immersive user experience.(迷人的,PWA有着近乎原生app般的用户体验)
而在google更具体的定义下,PWA至少应具有这些特性:
渐进式:可以确保每个用户都能够打开网页
响应式:所有硬件设备如手机,pc都能够完美适配
离线应用:支持没有网络的情况下也可以打开网页
app化:体验近似app
常更新:经常处于最新的状态
安全:仅服务于https协议确保传输内容不会被篡改
可被发现:允许被搜索引擎识别
推送:在没有打开app的情况下可以获取到推送信息
可安装:能够像app一样被添加到桌面
可跳转:只需一个链接即可访问到你的web app
想让自己的web app升级成为PWA,绕不开PWA三个关键的技术:
-
Service Worker
-
Manifest
-
Push Notification
下面我会逐一为大家介绍三者的概念
ServiceWorker
Service worker算是PWA中的最核心内容了。相比于浏览器默认提供的workers, service worker是一种特别的事件驱动的worker,特别之处在于它的生命周期与当前页面无关,当前页面未关闭也可以退出,当前页面未打开时也可以启动。也就是,service worker提供了web应用通常不具有的离线能力。在网络不稳定的情况下,可以操作cache获取数据,并保持页面在离线状态下也能正常显示。(达观数据 施列宇)
你可能会问AppCache也具有同样的离线能力,为什么我们不能使用AppCache呢?实际上AppCache这项技术本身存在更新,存储大小,路径问题。在多页面应用方便,AppCache还存在着明显的缺陷。而Service Worker可以很好的规避这些问题。
Service Worker的启用条件是1.必须是https协议或者localhost环境下,2..浏览器支持。有了这两个先决条件,我们就可以使用Service Worker进行PWA开发了。
Service Worker兼容性目前进展
生命周期是Service Worker中比较复杂的一部分了,如果不能了解它的整个周期,在使用过程中,你可能会有一种失控的感觉。
Service Worker的生命周期包含六种状态:parsed, installing, installed. activating, activated, redundant。状态之前的转换过程可以用一张图来表达。
Service Worker的生命周期
Parsed(解析成功): 页面注册Service Worker时,浏览器解析脚本并获取入口点。解析成功,就可以访问serviceworker对象了。
Installing(正在安装):Service Worker在解析完成后,浏览器会进行安装。如果安装失败会直接进入到redundant(废弃)状态。(达观数据 施列宇)
Installed/Waiting(安装成功/等待状态): 如果ServiceWorker成功安装,Service Worker会处于等待状态,等待事件响应。
Activating(正在激活): 处于等待状态下的Service Worker如果感知到以下几件事儿,将会进入activating状态中:1.Service Worker脚本中self.skipWaiting()方法被调用;2.用户已关闭service worker作用域下的所有页面;3.页面超时。Acticating失败也会使Service Worker进入Rendundant状态。
Activated(激活成功): 激活成功状态。
Redundant(废弃): 废弃状态,Serivce Worker处于这个状态就会停止工作,需要开发者去检查哪一个环节出了问题。
Manifest(应用清单
PWA提供了一个manifest.json清单文件来向浏览器暴露web应用的元数据,包括名称,icon的url等。以备浏览器使用,比如在添加至主屏或推送通知时暴露给操作系统,从而增强web应用于操作系统的集成能力。
Manifest在PWA中的作用大致有:
- 将PWA添加至手机屏幕上
- 在app中全屏启动,不显示地址栏
- 控制屏幕横竖屏
- 定义PWA启动画面
- 设置应用的启动方式,是从主屏幕启动还是从URL启动
- 设置添加屏幕上的应用程序的基本属性,如名称,图标
Push Notification(消息推送)
Service worker中提供了消息推送的功能。消息推送在原生app或者hybird app中已不鲜见。消息推送到页面,意味着页面预先知道有些事情要发生,并把这些事情做好。比如,提前准备好页面需要的资源。推送的服务器,chromium默认使用的是GCM/FCM,目前由于某些原因还无法在国内进行访问,国内暂时也没有浏览器厂商支持标准的推送服务。
介绍了PWA使用到的核心技术,下面我们来创建一个简单的PWA。
在使用Service之前,需要先判断宿主对象navigator中是否含有servicerWorker对象。如果存在,则可以通过serviceWorker对象的register方法进行注册。
注册Service Worker
注册过程中,浏览器会解析serviceWorker注册文件,在此期间出现任何错误,service Worker都会进入Redundant状态。(达观数据 施列宇)
Service Worker成功执行,install事件就会被激活,install完成后,service worker进入就绪状态,可以进行使用了。
install事件预处理安装逻辑,使用skipWaiting方法让service worker直接进入activating状态
service worker对象监听fetch对接,在此觉得是否需要使用service worker缓存文件亦或是原地址内容。
使用caches.match方法判断当前request是否为已缓存内容
除此之外,我们也需要及时将过期的静态资源清除掉,当web更新,某些文件添加了新的版本号,可以通过activate事件回调,清除掉过期资源。然后使用clients.claim方法取得页面控制权,这样新页面打开则会使用新的service worker,旧的service worker对象则会进入redundant状态。
使用activate事件处理过期资源
这样一个支持PWA的web app已经搭建起来了,刷新页面后可以从chrome network中看到几个缓存的静态资源来源是from ServiceWorker。
从network中看出部分资源是从service worker加载而来的
达观数据使用了Angular作为前端技术栈,我们前端技术团队在研究pwa支持的同时也考虑了前端项目在angular项目中的兼容性。
Angular在6.0版本加入了PWA的支持,想要支持PWA特性需要先将angular,angular-cli升级到6+.
使用ng add @angular/pwa添加PWA特性支持。添加后会检测到angular.json,ngsw.json,manifest.json等多个文件被编辑或被创建。其中ngsw.json是angular的PWA特性的配置文件。(达观数据 施列宇)
使用ng build –prod –build-optimizer 命令将代码打包,将代码部署后会看到静态资源都来源于serviceWorker,也就证明PWA添加成功了。
google作为PWA的推行者,自家的浏览器也最早带上了PWA调试工具,方便开发者进行功能调试。
开发者通过F12打开调试窗口,选择application,下方会有service workers相应的窗口。这里可以看到当前域下有哪些serviceworker对象,可以观察到他们当前的状态,service worker对象文件详情等信息。也可以通过offline勾选项切换无网络状态下页面的反应,update on reload强制每次刷新都重置service worker进行install; Bypass for network切换不支持service worker窗口下的页面呈现状态。可以说都是很棒的调试功能。(达观数据 施列宇)
chrome service worker调试窗口
大家也可以在chrome://serviceworker-internals中了解浏览器中所有的service worker状态。
BOUT
关于作者
施列宇:达观数据前端技术专家,负责达观数据毕昇系统,仓颉系统等项目的研发,对数据挖掘在前端产品中落地,前端数据可视化,标准化工程化有着多年的研究。