PWA技术解析及爱奇艺PC端的实践

2020 年 1 月 03 日

PWA技术解析及爱奇艺PC端的实践

写在前面


文章开始之前,我们先来讲讲 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%。目前爱奇艺主站为了保持站点的统一性,实践了桌面快捷启动。未来我们会继续尝试实践离线工作,消息推送,换肤,基于用户行为分析智能调整常用频道和展示界面等功能,为给用户带来更高的体验,力争打造一款极速极简版爱奇艺。


2020 年 1 月 03 日 10:191005

评论 1 条评论

发布
用户头像
PWA 技术用来解决以上问题,实现让 Web“摆脱”浏览器,拥有原生应用的使用体验和性能,从而真正实现跨全平台的应用。
2020 年 01 月 03 日 10:59
回复
没有更多评论了
发现更多内容

[架构师训练营第 1 期] 第五周学习总结

猫切切切切切

极客大学架构师训练营

第01周学习总结[架构师训练营第 2 期]

Airship

极客大学架构师训练营

架构训练营第五周作业

Geek_ce484f

极客大学架构师训练营

食堂就餐卡系统设计

水浴清风

一致性Hash算法的实现及分析

天天向上

极客大学架构师训练营

架构师训练营第二期 Week 1 总结

bigxiang

【第五周】课后作业

云龙

食堂就餐卡系统设计

Sandman

极客大学架构师训练营 作业

架构师训练营 1 期第 4 周:系统架构 - 作业

灵霄

极客大学架构师训练营

食堂就餐系统

落朽

第一周学习总结

Alvin

学习 极客大学架构师训练营 2组

week5

张兵

极客大学架构师训练营

架构训练营第五周作业总结

Geek_ce484f

极客大学架构师训练营

Netty源码解析 -- ChannelOutboundBuffer实现与Flush过程

binecy

源码分析 Netty nio

架构师训练营第 1 期 - 第五周作业提交

Todd-Lee

极客大学架构师训练营

架构师训练营第 1 期 -Week5 - 技术选型一学习总结

鲁小鲁

极客大学架构师训练营 负载均衡架构 缓存架构 消息队列架构

[架构师训练营第 1 期] 第五周命题作业

猫切切切切切

极客大学架构师训练营

架构师训练营 - 作业 - 第五周

Max2@12

架构设计学习笔记1

Arthur

极客大学架构师训练营

技术是否要追新?基于4点判断谈谈4点认识

田维常

程序员 技术 最新 技术追新

【第五周】技术选型(一)

云龙

架构师训练 第一周 学习总结

阿光

一致性哈希算法 Java 实现

escray

极客大学 极客大学架构师训练营 课程作业

架构师训练营第 1 期 -Week5 - 课后练习

鲁小鲁

极客大学架构师训练营

week05学习总结

追风

架构师一期

架构师训练营第二期Week 1作业

bigxiang

极客大学架构师训练营

架构师训练营第 5 周学习总结

netspecial

极客大学架构师训练营

极客时间第 2 期架构师训练营第一周作业 1

willson

【原创】90%的人都不会做的一道笔试题

田维常

程序员 面试

架构师训练营 Week5 - 课后作业

算法 分布式缓存 一致性哈希

架构师训练营 1 期第 4 周:系统架构 - 总结

灵霄

极客大学架构师训练营

PWA技术解析及爱奇艺PC端的实践-InfoQ