You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The path of the provided scope ('/') is not under the max scope allowed ('/public/'). Adjust the scope, move the Service Worker script, or use the Service-Worker-Allowed HTTP header to allow the scope.
消息推送是 App 保活冲绩效的常用手段,由于 HTTP 是一个无状态协议,推送功能在用户关闭了浏览器之后便没了办法,这一次 PWA 赋予了 Web 这个能力。
其中便包含了两个技术点
推送 push:连接服务端和 SW 进行消息传递
通知 notification:控制客户端(浏览器)进行消息提示
下面我们来解析一个通知体
// 消息体的 titleself.addEventListener('push',event=>{consttitle="Credit Card";constoptions={// 主内容"body": "Did you make a $1,000,000 purchase at Dr. Evil...",// 视觉配置,如 icon,Badge,image 等,不同的视觉配置展示的位置也不同// 详情参看 https://lavas.baidu.com/pwa/engage-retain-users/notification/notification-display"icon": "images/ccard.png",// 震动设置,其中的数字以2个为一组,分别表示震动的毫秒数,和不震动的毫秒数"vibrate": [200,100,200,100,200,100,400],// 铃声"sound": "path/to/sound.mp3",// 标签,用于客户端消息归类"tag": "request",// actions,用户操作后会将结果反馈给浏览器"actions": [{"action": "yes","title": "Yes","icon": "images/yes.png"},{"action": "no","title": "No","icon": "images/no.png"}]}// 激活通知self.registration..showNotification(title,options);});self.addEventListener('notificationclick',event=>{// Do something with the event event.notification.close();});self.addEventListener('notificationclose',event=>{// Do something with the event });
什么是 PWA
Progressive Web App, 简称 PWA,是「渐进式」提升 Web App 体验的一种新方法,能给用户类似原生应用的体验。
「高可靠,高性能,优体验」是 PWA 惯用的形容词,他的另外一个优点就是「渐进式」,开发者可以对照 PWA Checklist 逐步对自己站点进行 PWA 化升级。
PWA 的发展史
2007
苹果前 CEO,Steve Jobs,2007 年 WWDC 上提出了为初代 iPhone 开发应用的概念,当时所介绍的,就是 Web App——可以从主屏直接启动的 Web 应用。
图片来源 appleinsider.com
可惜当时这个理念太过超前,并没有引发太多关注,反而是后来的原生 App 应用更符合当时的市场需求,互联网公司更愿意投入人力在原生 App 的开发上,而忽略了 Web。因此原生 App 的大量出现,占据了移动时代的主流地位,Web 似乎就要被 App 所取代。
2014
随着 Web 技术的发展,时间来到 2014 年, W3C 公布了 Service Worker 的相关草案,其生产环境在 2015 年被 Chrome 支持。随后 PWA 加以完善,相关技术不断升级优化,在用户体验和用户保活两方面的可发掘价值越来越大。
2017
继移动站点喷井式发展之焰末,原生 App 的弊端越发明显,对于它来讲,最大的痛点便是其天生封闭的基因导致的内容无法被索引,相对的 Web 站点可索引的优势开始凸显,与此同时,PWA 遵循 W3C 标准开发的技术,完全开放,能够快速地被各大浏览器厂商支持,市场支持度一夜崛起。
另外一边,App 的推广并不顺利,据调查统计,移动设备用户 80% 的时间花费在了常用的 5 个应用上,16年近一半的美国用户平均每月安装「0」个新 App,用户积极探索新 App 已经成为了过去式,拉新和保活的成本越来越高。
原生 App 的发展遇到了天花板,推广也正向瓶颈一步步靠近,Web 看到了自己的机遇,PWA 以及支撑 PWA 的一系列关键技术应运而生。
2018
2018 年对于 PWA 来说是里程碑的一年,万众瞩目的 Apple 终于在 iOS 11.3 里支持了 Web App Manifest,以及内置的 Safari 11.1 支持了 Service Worker。
与此同时,全球顶级浏览器厂商,Google、Microsoft、Apple 已经全数宣布支持 PWA 技术,这预示着,Web App 将会迎来全新的时代
2019
截至当下的 PWA 支持度
依据 Can I use 的统计(20190515)
Service Worker 以全数「登船」。信息来源于 https://jakearchibald.github.io/isserviceworkerready/#moar
PWA 的核心
PWA 有几个核心功能,分别是「离线,安装,推送」
离线浏览
弱网或离线的情况下依然可以「正常访问」甚至「秒开」,这种体验甚至超过了 app。主要的技术点就是 Service Worker。
Service Worker
SW 类似于我们熟知的 Web Worker,Web Worker 可以脱离主线程,处理一些「脏累」活,干完后通过 postMessage 向主线程汇报工作结果。所以,SW 也是脱离主线程的存在,与 Web Worker 不同的是,SW 具有持久化的能力。
SW 还具备有以下功能和特性:
基于以上我们可以看到 SW 要让缓存做到极致优雅的伟大使命。
Service Worker 的生命周期
想要灵活的使用 SW 功能,就要充分了解他的生命周期,以及各阶段的状态。
以下是 MDN 给出的 SW 的详细生命周期图。
可以看到,SW 的生命周期包含这么几个状态
安装中
,安装后
,激活中
,激活后
和废弃
安装( installing ):这个状态发生在 Service Worker 注册之后,表示开始安装,触发 install 事件回调指定一些静态资源进行离线缓存。
install 事件回调中有两个方法:
event.waitUntil():传入一个 Promise 为参数,等到该 Promise 为 resolve 状态为止。
self.skipWaiting():self 是当前 context 的 global 变量,执行该方法表示强制当前处在 waiting 状态的 Service Worker 进入 activate 状态。
安装后( installed ):Service Worker 已经完成了安装,并且等待其他的 Service Worker 线程被关闭。
激活( activating ):在这个状态下没有被其他的 Service Worker 控制的客户端,允许当前的 worker 完成安装,并且清除了其他的 worker 以及关联的旧缓存资源,等待新的 Service Worker 线程被激活。
activate 回调中有两个方法:
event.waitUntil():传入一个 Promise 为参数,等到该 Promise 为 resolve 状态为止。
self.clients.claim():在 activate 事件回调中执行该方法表示取得页面的控制权, 这样之后打开页面都会使用版本更新的缓存。旧的 Service Worker 脚本不再控制页面,之后会被停止。
激活后( activated ):在这个状态会处理 activate 事件回调 (提供了更新缓存策略的机会)。并可以处理功能性的事件,fetch (请求)、sync (后台同步)和 push (推送)。
废弃状态 ( redundant ):这个状态表示一个 Service Worker 生命周期的结束。
这里特别说明一下,进入废弃状态的原因可能为这几种:
安装 (install) 失败
激活 (activating) 失败
新版本的 Service Worker 替换了它并成功激活
Service Worker 支持的所有事件
MDN 也列出了 Service Worker 所有支持的事件:
install:Service Worker 安装成功后被触发的事件,在事件处理函数中可以添加需要缓存的文件
activate:当 Service Worker 安装完成后并进入激活状态,会触发 activate 事件。通过监听 activate 事件你可以做一些预处理,如对旧版本的更新、对无用缓存的清理等。
message:Service Worker 运行于独立 context 中,无法直接访问当前页面主线程的 DOM 等信息,但是通过 postMessage API,可以实现他们之间的消息传递,这样主线程就可以接受 Service Worker 的指令操作 DOM。
Service Worker 有几个重要的「功能性事件」,这些功能性的事件支撑和实现了 Service Worker 的特性。
fetch (请求):当浏览器在当前指定的 scope 下发起请求时,会触发 fetch 事件,并得到传有 response 参数的回调函数,回调中可以做各种代理和缓存操作。
push (推送):push 事件是为推送准备的。不过首先需要了解一下 Notification API 和 PUSH API。通过 PUSH API,当订阅了推送服务后,可以使用推送方式唤醒 Service Worker 以响应来自系统消息传递服务的消息,即使用户已经关闭了页面。
sync (后台同步):sync 事件由 background sync (后台同步)发出。background sync 配合 Service Worker 推出的 API,用于为 Service Worker 提供一个可以实现注册和监听同步处理的方法。但它还不在 W3C Web API 标准中。在 Chrome 中这也只是一个实验性功能,需要访问 chrome://flags/#enable-experimental-web-platform-features ,开启该功能,然后重启生效。
Service Worker 的使用
有了以上 SW 的事件及 API,接下来就是实战部分了。
先决条件
127.0.0.1
和localhost
测试,但部署须在 https 协议下。巧妇难为无米之炊,以上两个先决条件是必须要满足的。
注册 Service Worker
其实,关键代码只有一行
注意,此处有坑
Service Worker 的注册路径决定了其 scope 默认作用域,如 SW 注册文件的路径为
https://www.a.com/public/sw.js
时,对应默认 scope 是/public/
,其作用范围如下以上可看出,当作用域 scope 为
/public/
后,其作用范围只限于本身和子域,父域和兄弟域皆无效,跨域就更免谈了。当然,我们可以通过设置 scope 来限定自己的作用域,但是!请注意,『以下写法是错误的』。
以上写法均会报错
所以,sw.js 文件最好放在根域名下
如
当 scope 不同时,请求被监控情况也有不同
查看是否注册成功
我们可以通过打开 Chrome 的
DevTools
->Application
->Service Workers
查看 SW 的注册情况。看到类如
Status: #xxxx activated and is running
,即说明注册并激活成功。也可以通过打开 Chrome 的管理页
chrome://inspect/#service-workers
查看安装 Service Worker
在受控页面启动注册流程后,我们来看看处理 install 事件的 Service Worker 脚本。
最基本的例子是,您需要为安装事件定义回调,并处理想要缓存的文件。
在 install 回调的内部,我们可以执行以下步骤(当然也可以啥也不干):
此处,我们以所需的缓存名称调用
caches.open()
,之后再调用cache.addAll()
并传入文件数组。 这是一个promise
链(caches.open()
和cache.addAll()
)。event.waitUntil()
方法带有promise
参数并使用它来判断安装所花费的时间,以及安装是否成功。如果所有文件都成功缓存,则将安装 Service Worker。 如有任意文件无法下载,则安装失败。此设计可保证 SW 启动的正确性,但过长的资源列表也增加了安装失败的几率,可根据项目情况自行定义,也可不定义。
自定义请求响应
在安装 Service Worker 且用户转至其他页面或刷新当前页面后,Service Worker 将开始接收 fetch 事件。下面提供了一个示例。
如果希望连续缓存新请求,可以通过处理 fetch 请求的响应并将其添加到缓存来实现,如下所示。
workbox
上一部分介绍了 SW 的使用,以及自定义请求响应,实际上,
fetch
的玩法有很多,但也都是大同小异。因此,为了使 SW 更容易使用,GoogleChrome 团队在 Chrome Submit 2017 上首次推出的一套 Web App 静态资源和请求结果本地存储的解决方案 workbox。
来直接感受下 workbox 的语法
一看就懂,是不是很简单呢?
这里有个缓存策略,简略介绍一下。
此策略会优先匹配缓存,如果未命中,则透传网络,如果命中则返回缓存响应,同时在后台更新缓存网络响应,此策略比较安全,更像是竞争策略,谁快谁响应。
Network First
网络优先策略,如果网络通畅,返回网络响应并缓存,如果离线,则返回缓存响应
Cache First
缓存优先策略,如果缓存匹配,返回响应,如果不匹配则透传网络,并缓存「有效」响应
Network Only
强制网络响应,即为普通请求
Cache Only
强制缓存响应,无匹配则返回 404
更多关于 workbox 请前往 https://developers.google.com/web/tools/workbox/
可「安装」
PWA 另外一个爆点就是「可安装」,学名叫作「添加到主屏幕」,这归功于一个配置文件
manifest.json
,它给予开发者自定义图标、显示名称、启动方式等信息并添加至桌面的能力,同时也提供 API 方便开发者管理网络应用安装横幅,让用户可以方便快捷地将站点添加到主屏幕中。支持度
当前 manifest.json 的标准仍属于草案阶段,Chrome、Firefox 和 Apple 都已经实现了这个功能或者功能的部分,微软正努力在 Edge 浏览器上实现。
在 caniuse 中可查到 manifest 的支持度,数据显示 92.64% 的移动浏览器已经达到了支持或者部分支持的程度,想必在不久以后,当规范标准通过后,manifest 的支持度可以达到一个新高度。
配置
我以一个相对完整的
manifest.json
配置文件进行讲解配置介绍
测试
配置完之后就可以在 Chrome 的 DevTools 中进行验证测试了。
图片来源于 developers.google.com
可推送消息
消息推送是 App 保活冲绩效的常用手段,由于 HTTP 是一个无状态协议,推送功能在用户关闭了浏览器之后便没了办法,这一次 PWA 赋予了 Web 这个能力。
其中便包含了两个技术点
下面我们来解析一个通知体
以上的消息配置,展示的结果如下图。
关于推送功能的更多实操不属于本文探究的范畴,有实际需求的同学可以前往官网进行了解。
传送门>>
https://developers.google.com/web/fundamentals/push-notifications/
https://lavas.baidu.com/pwa/engage-retain-users/notification/notification-pattern
PWA & 小程序
有人说「PWA 是小程序的祖宗」,不无道理,PWA 对小程序肯定存在一定的借鉴意义,但是否会挤压 PWA 的市场?我们应该放心,小程序的设计并不是 Web 的替代者,而是介于原生 App 和 Web 之间的存在。
小程序更倾向于轻便及时触手可得。既没有原生 App 的「沉重」也没有 Web 「迟钝」。在此得天独厚的基础之上加之以「社交流量」的加持,微信小程序的存在并非偶然。
但是,如果没了网络,一样玩不转;主流的搜索引擎并无法捕获小程序的内容。所以,App、Web 和小程序是相辅相成的。
另外,笔者想表达另外一个观点
在经历过一段痛苦的微信小程序洗礼之后,我们「欣然」接受了。奈何众XX小程序『竞相开放,争奇斗艳,不亦乐乎』。殊不知,我等不才,竟要为了这区区语法之差异,彻夜无法停歇,然,产与出相比,孰轻孰重?
唉~程序员奈何为难程序员~~
总结
关于 PWA 的技术早在 2 年前即已相对完整,只是由于「天朝人民太过赋予」,对支持与否未发布意见的 Apple 在天朝市场有着举足轻重的地位,而「外围」仿佛对 Android 机更为推崇,所以,PWA 在国内的发展和推广并不理想。
此时此刻,PWA 的支持度也达到了一个相对让人满意的水平,虽然体验依然无法和原生 App 相提并论,但作为 App 短板的补丁已是绰绰有余。
所以,『架构师』们,可以盘起来了。
以上就是 PWA 的相关知识点,希望对你有所帮助。
[1]. https://developers.google.com/web/fundamentals/web-app-manifest/
[2]. https://developers.google.com/web/fundamentals/primers/service-workers/
[3]. https://developers.google.com/web/tools/workbox/
[4].下一代 Web 应用模型 —— Progressive Web App
[5]. https://lavas.baidu.com/
The text was updated successfully, but these errors were encountered: