写在前面
文章开始之前,我们先来讲讲 PWA,Progressive Web App 的缩写,全称直译过来就是渐进式网页应用,也就是一种网页应用,它可以离线使用,可以变成独立应用安装到系统中。它非常的轻量化,在多平台上面拥有一致的界面。
PWA 的概念是由 Chrome 项目组在 2015 年的时候提出,很明显,它是一种基于网页的应用,但它又与传统的 Web App 又有一些不同,下文具体与大家分享 PWA 技术解析及在爱奇艺 App 的实践。
概述
渐进式网页应用(下文简称 PWA),是提升 Web App 体验的一种新方法,能给用户原生应用的体验。自 Web 技术诞生至今,前端开发一直拥有一个最为独特的优势:跨平台。只要是符合 W3C 规范的网页,就可以在任何设备及任何浏览器上进行访问。由于终端设备呈爆发性增长态势,当下跨平台优势尤为重要,并且在可预见的未来,智能终端的种类和数量还会进一步扩大。
但这种跨平台的优势,没有在原生应用(Applications)这一关键的领域充分发挥作用。如果你要开发一款应用,仍然需要考虑可能涉及到的平台,并为每个主要平台开发一个单独的版本。
由此我们产生一个疑问,为什么 Web 的跨平台能力只存在于网页中?为什么不能把这种能力应用到软件开发中呢?如果我们开发一次,就可以在所有平台上使用,将会大幅提升开发效率。
早期应用的实践都是为了同样的课题:如何用 Web 技术来开发原生应用,如 Electron、Cordova、React Native。PWA 则更进一步:直接用 Web 技术本身实现原生应用的体验。
PWA 是什么
想要用 Web 技术来实现原生应用的体验,至少我们需满足以下条件:
在任何设备上都能运行;
能快速打开、使用且可安装;
能在浏览器中打开并支持桌面快捷方式启动;
拥有独立窗口;
支持离线工作;
与系统功能集成;
良好的性能
PWA 技术用来解决以上问题,实现让 Web“摆脱”浏览器,拥有原生应用的使用体验和性能,从而真正实现跨全平台的应用。
在移动端为主的时代,用户倾向使用原生应用,因为 Web 在以下几个关键点上与原生应用仍有差距:
高质量UI:原生应用有更高质量的UI界面,交互更符合移动设备的使用方式。
程序入口图标:这是原生应用最主要的优势,移动设备打字不便,用户都喜欢从桌面图标点击进入,通过web访问操作过于繁琐。
系统集成:原生应用和系统匹配,可以利用很多附属功能(通知、分享、设置等等)。
有了 PWA 技术后,Web 应用可以安装到桌面,拥有自己的固定入口,并且可以调用很多系统功能,实现原生应用的体验。开发者可以通过一套代码的开发,实现全平台的适配(现已支持 IOS 系统):
PWA 之所以能实现原生应用的体验,不是靠某一项特定的技术,而是通过一系列新技术的应用,使得 Web 开发在安全、性能和体验三个方面得到明显提升。PWA 本质上是 Web App,但兼具了 Web App 和 Native App 的优点。
PWA 的主要特点包括下面三点:
可靠 - 即使在不稳定的网络环境下,也能瞬间加载并展现,并且可以实现离线使用
快速 - 快速响应,用平滑的动画响应用户的操作
沉浸式体验 - 媲美设备上的原生应用,沉浸式的用户体验,还可以添加到桌面
PWA 强调渐进式:不要求一次性达到安全、性能和体验上的所有要求。用户即使不安装,也能在浏览器中顺畅访问该 Web App 的内容。因此,开发者也可以逐步改进自己的 PWA 项目,陆续添加更多功能。
PWA 技术原理解析
我们提到 PWA 的三个主要特点:可靠、快速、沉浸式体验:
可靠和快速,意味着在网络不稳定甚至没有网络时,依然可以给用户提供较为良好的使用体验,并且确保较好的性能。为了实现上述目标,PWA使用了一项新的技术:Service Worker,这项技术可以实现前端直接处理网络请求,起到类似于中转服务器的作用,同时由于Service Worker是独立线程,执行过程对于页面性能影响很小,可以同时保障主线程的流畅执行。
沉浸式体验,意味着要有固定的桌面图标、独立简洁的运行窗口、可扩展的系统功能(例如通知)等。PWA引入了manifest.json文件,配合Service Worker实现了Web App的可安装特性,可定制桌面图标、窗口模式等多方面配置,实现与原生应用一致的使用方式。
因此,我们接下来主要介绍两个内容:
Service Worker技术。
如何配置实现PWA的可安装。
1. Service Worker
丰富的离线体验、定期的后台同步、推送通知等——这些本来属于原生应用的功能,PWA 在 Web 技术中进行了实现,而 ServiceWorker 就是所有这些功能所依赖的技术基础。
什么是 Service Worker
Service Worker 是浏览器在后台独立于网页运行的脚本,可以实现对于网络请求的拦截处理,且支持推送通知和后台同步等功能。未来 ServiceWorker 将会实现定期同步或地理围栏等功能,不断完善对于设备 API 的调用。本文主要讨论 Service Worker 的核心功能:拦截和处理网络请求,以及缓存管理。
编写 Service Worker 时,需要注意以下几点:
Service Worker是一种JavaScriptWorker,不能直接访问 DOM。因此ServiceWorker需要通过postMessage与页面主线程进行通信,而页面则可以对 DOM 执行操作;
Service Worker 是一个可编程的网络代理,我们可以通过Service Worker来决定页面所发送网络请求的处理方式,相当于前端有了自己可以编写的中转服务器;
Service Worker不使用时会被中止并在下次有需要时重启,所以不能依赖 Service Worker的onfetch和onmessage处理程序中的全局状态。如果有需要持续保存并在重启后加以重用的信息,建议使用IndexedDB API存储状态。
Service Worker 的生命周期
Service Worker 的生命周期独立于网页。要安装一个 Service Worker,我们需要经历:注册——安装——激活三大步骤。
想要为指定网页安装 Service Worker,我们需要先在页面中注册 Service Worker,注册执行后,浏览器在后台会启动 Service Worker 的安装步骤。
在安装过程中,通常我们会缓存一些静态资源。如果所有文件都成功缓存,那么 ServiceWorker 就会成功安装。若任何文件下载失败或缓存失败,那么安装也会随之失败。如果发生安装失败的情况,下次访问页面时,Service Worker 会再次尝试安装。
安装完成后进入激活步骤,在这一阶段旧缓存会被处理。
激活后,Service Worker 的代码就可以对其作用域内的所有页面实施控制,首次注册的 Service Worker 需要页面再次加载后才会生效。
以下是 Service Worker 初始安装时的简化生命周期:
四个基本环节:注册 - 安装 - 启动 - 更新
下图则是一个 Service Worker 更为详细的一个生命周期过程,供大家了解 Service Worker 的运行过程:
Service Worker 运行的前提
浏览器支持:适用浏览器范围日益广泛。目前,Service Worker 受 Chrome、Firefox、Opera、MicrosoftEdge的支持,safari或将支持此功能;
设置HTTPS协议:在开发过程中,开发人员可以通过 localhost 使用Service Worker,但如果要在网站上部署 Service Worker,则需要在服务器上设置 HTTPS。
2. 实现 PWA 的可安装
清单文件
为了实现 PWA 的可安装,首先我们需要在页面里加载一个清单文件(manifest.json),在这个 JSON 文件中提供有关应用程序的信息(例如名称,启动地址,图标和描述)。manifest 文件的作用是将 Web 应用程序安装到设备的主屏幕,为用户提供更快的访问和更丰富的体验。
下面是一个清单内容的示例:
Web 应用程序清单部署在 HTML 页面中,使用于文件头部的一个链接标记:
实现安装的必备条件
为了能够实现安装功能的弹出,需要满足以下条件:
Web App还没有被安装。且 prefer_related_applications不是true。
用户是常用用户(Chrome浏览器会对用户是否多次访问目标网站进行判断)
页面内需要有清单manifest.json文件,且文件内必须有以下字段:
short_name or name;
icons官方推荐包括 192px 和 512px 尺寸的图标;
start_url;
display值必须属于以下范围:fullscreen, standalone,or minimal-ui
需要在 HTTPS 协议下(service worker运行的前提)
注册了一个serviceworker,且service worker内有fetch事件监听
当以上条件都满足后,Chrome 会触发 beforeinstallprompt 事件,我们便可以通过监听该事件来实现安装提示的弹出。
监听 beforeinstallprompt 事件后,存储事件对象 e,待用户点击安装按钮时再执行 e.prompt()方法弹出系统安装弹窗:
当用户在系统安装弹层处点击了安装按钮后,Web 应用会被添加到桌面,实现 PWA 的安装。此后,用户便可以通过桌面图标来访问这个 Web 应用。
爱奇艺 PC 端 PWA 实践
Service Worker 在爱奇艺登录的应用
在爱奇艺主站的登录页面,我们最先使用 Service Worker 技术来进行网络处理的优化,对常用的 CSS、JS 以及图片资源进行缓存,令登录窗口的展现速度明显提升,详见下图:
从图中我们可以看出:从 response start 开始的网络响应时间明显降低。更为重要的是,从右侧的“页面加载时间分布”图可以看出,使用 Service Worker 后页面加载时间非常稳定,网络波动对于页面加载造成的影响很小,这对于用户的实际体验会有明显的加分。
爱奇艺主站 PWA 应用
爱奇艺主站已支持 PWA 的快捷安装。
在访问爱奇艺主站首页时,页面右下角会有一个加号图标,鼠标放在该处会显示一个安装弹层,如下图:
当点击“立即添加”后,页面会出现系统选框,询问是否安装此 PWA 应用:
选择安装后,桌面上会出现一个新的 App 图标,即为打开 PWA 应用的入口。点击图标,打开爱奇艺快捷版,可以看到一个界面更加简洁的爱奇艺首页,没有浏览器的 Tab 标签、地址栏以及工具栏等:
遇到的问题及优化方案
登录应用 Service Worker 做缓存处理遇到的主要问题是:如何兼顾快速显示和缓存更新,以及跨域的资源要如何保证缓存完整?
为了快速显示,用户请求资源时,用Service Worker拦截并直接返回缓存,免去了向远端请求的耗时;
为了避免缓存更新不及时,页面加载完成后再去远端请求一遍相应资源更新缓存,确保及时更新缓存内容,也同时避免跨域资源缓存不完整的问题。
在将网页转为PWA的过程中,针对PWA与网页的机制区别,现已进行了一些优化处理:
点击跳转优化:爱奇艺主站的页面跳转为新开标签页,但PWA只有一个单页面,因此当用户在PWA中访问爱奇艺时,对页面内的点击事件会转为当前页面跳转,避免打开浏览器新页面,保证用户的沉浸式体验。
代码示例:
记录上次打开地址:PWA启动时只支持打开首页,通过记录用户最后一次打开的地址,为用户恢复上次关闭的页面,便于继续观看。
代码示例:
数据效果及未来规划
PWA 上线后用户留存率与爱奇艺主站相比,提高了 9%。目前爱奇艺主站为了保持站点的统一性,实践了桌面快捷启动。未来我们会继续尝试实践离线工作,消息推送,换肤,基于用户行为分析智能调整常用频道和展示界面等功能,为给用户带来更高的体验,力争打造一款极速极简版爱奇艺。
评论 1 条评论