# PWA

# 前言

PWAProgressive Web Apps ),即为渐进式网络应用。突破了以往 web 应用只能依赖于互联网分发与依赖浏览器的两种方式。瞬间打开了 web 应用从性能、架构到用户体验的一系列可能性。同时,PWA 技术属于 web 标准。因此也具备了一套代码发布可以同时跨桌面端设备、跨操作系统、跨浏览器的超级应用。同时,在国内也有微博,饿了么使用 PWA 技术发布专门的 PWA 产品。也可以说从生态、工具链都已经成熟。

# 什么是PWA

PWA 它不是特指某一项技术,而是应用多项技术来改善用户体验的 Web App,其核心技术包括 Web App ManifestService WorkerWeb Push 等(在后续进行简单说明),用户体验才是 PWA 的核心。

# PWA 的特点

PWA 主要特点如下:

  • 可靠 - 即使在网络不稳定甚至断网的环境下,也能瞬间加载并展现
  • 用户体验 - 快速响应,具有平滑的过渡动画及用户操作的反馈
  • 用户黏性 - 和 Native App 一样,可以被添加到桌面,能接受离线通知,具有沉浸式的用户体验

# PWA 的特性

PWA 本质上还是 Web App,借助了新技术具备了一些 Native App 的特性,所以它兼具 Web AppNative App的优点,同时在安全、体验和用户黏性三个方面都有很大的提升。总结下来,PWA 具有如下特性。

  • 渐进式 - 适用于所有浏览器,因为它是以渐进式增强作为宗旨开发的。在不支持的相关浏览器中可以传统web网页支持

  • 连接无关性 - 能够借助 Service Worker 在离线或者网络较差的情况下正常访问

  • 类原生应用 - 由于是在 App Shell 模型基础上开发,因此应具有 Native App 的交互,给用户 Native App 的体验

  • 持续更新 - 始终是最新的,无版本和更新问题

  • 安全 - 通过 HTTPS 协议提供服务,防止窥探,确保内容不被篡改

  • 可索引 - manifest 文件和 Service Worker 可以让搜索引擎索引到,从而将其识别为『应用』

  • 黏性 - 通过推送离线通知等,可以让用户回流

  • 可安装 - 用户可以添加常用的 Web App 到桌面,免去到应用商店下载的麻烦

  • 可链接 - 通过链接即可分享内容,无需下载安装

下表列出了传统 Web AppNative AppPWA 在各特性的对比。

是否可安装 是否可链接访问 用户体验 用户黏性
传统 Web 无法安装 可链接访问 体验一般 黏性差
Native App 可安装 不可链接访问 体验好 黏性强
PWA 可安装 可链接访问 体验好 黏性强

# PWA的核心技术

PWA 的核心是用户体验。能让 PWA 达到原生应用的体验并不仅仅依赖于某一项技术,而是多管齐下,进行改进,从而在安全、性能和体验上都获得很大的提升。下面介绍下其中最为核心的相关技术,分别是 Web App ManifestService Worker 、离线通知、App Shell 和骨架屏。

pwa实现

# Web App Manifest

web 应用清单文件是简单JSON文件,manifest.json。开发者可以在这个 JSON 文件中配置 PWA 的相关信息,应用名称、图标、启动方式、背景颜色、主题颜色等等。添加到桌面后,PWA 并不是一个快捷方式,而是能够在系统中作为一个独立的 App 存在的,用户可以设置它的权限,清除它的缓存,就和 Native App 一样。

微信截图_20200116165028.png

添加主屏的好处是显而易见的,主要有以下两方面的优点:

  • 缩短了用户和站点的距离,用户可以在主屏直达站点
  • 是能够让网站具有更加接近 Native App 的体验,具有启动画面、沉浸式浏览体验

下图就是 pwa 应用添加到桌面的步骤以及启动的效果:

# Service Worker

Service WorkerPWA 中最重要的功能就是离线与缓存

它是浏览器在后端独立于网页主进程运行的脚本,它可以拦截网络请求,可以操作本地缓存,还可以接受服务器推送的离线消息,它的功能很丰富,并且 Service Worker 可扩展性很强,想象空间比较大,未来 PWA 很多的特性会基于 Service Worker 来设计,这也是笔者为什么说它是 PWA 的心脏。

server_browser_service_worker.png

简单归纳一下,Service Worker 的特点,如下:

  • 一个特殊的 worker 线程,独立于当前网页主线程,有自己的执行上下文
  • 一旦被安装,就永远存在,除非显示取消注册
  • 使用到的时候浏览器会自动唤醒,不用的时候自动休眠
  • 可拦截并代理请求和处理返回,可以操作本地缓存,如 CacheStorageIndexedDB
  • 离线内容开发者可控
  • 能接受服务器推送的离线消息
  • 异步实现,内部接口异步化基本是通过 Promise 实现
  • 不能直接操作 DOM
  • 必须在 HTTPS 环境下才能工作

截止目前,在浏览器的兼容性上面也有着不错的表现。现如今已有高达92.45%的浏览器已经支持。在不支持的浏览器,可以以传统网页进行访问,不影响其功能。 微信截图_20200116171752.png

# 离线通知

在有了 Service Worker,其他功能才能发挥更大的作用,离线通知就是其中之一。

离线通知是指在用户 没有打开 PWA 站点的情况下,也能接受到服务器推送过来的通知并展现给用户,其中包括了两部分,离线推送和展现通知,分别是 Web PushNotification API

推送通知是一种时效性非常强的与用户沟通的方式,即使在 PWA 没有打开的情况下,依然可以触达用户,能够立即引起用户的注意,对于一些突发事件、限时活动、重大升级等时效性要求很高的场景,推送通知总是最好的选择,这也是过去 Native App 强于 Web App 的原因之一。因此 PWA 提供了 Web PushNotification API 补全了这一功能。

微信截图_20200117123013.png

在浏览器兼容方面,已经在绝大部分浏览器上所支持。但在 chorme49 上面部分支持(不支持 PushEvent.dataPushMessageData )。

标准Web Push的流程:

  • 页面向 Web 引擎注册 SW
  • 页面向 Web 引擎订阅消息, Web 引擎向 Push 服务器(GCM/FCM)订阅消息, Push 服务器返回订阅结果(Push Subscription,服务器地址)。页面将订阅结果(Push Subscription)发送给页面服务器。
  • 页面服务器向Push服务器推送消息,Push服务器向Web引擎推送消息,Web 引擎唤醒 SW,触发 SWonpush,页面处理 onpush 消息。

v2-3ca04e53ba386ab84074cc0291f0680f.jpg

Web Push应用起来并不容易,主要是 push service 需要浏览器自身去实现。而在谷歌的 Push Service(GCM/FCM)在国内是不可用的。

同时,在开始发送用户通知前,需要通过提示的方式获取他们的授权。如果用户拒绝,则无法发生任何消息,并且不会再给他们提示。

# App Shell 和骨架屏

App Shell 和骨架屏在提升首屏体验上发挥了重要作用。

App ShellPWA 界面展示所需的最小资源集合,即让页面能够正常运行起来的最小的 HTMLCSSJavaScript 等静态资源集,每个页面都需要加载这一部分资源。利用 Service Worker 把这部分资源缓存在本地,就能够在打开 PWA 时不需要从服务器端获取这部分资源,从而能够瞬间渲染出页面框架,不仅提升了首屏的速度,还减小了站点流量的消耗。

骨架屏(App Skeleton),也是提升首屏体验的有效方式。它的原理是在真实内容渲染完成之前,使用一些能够快速渲染的静态图片/样式/色块/部分真实内容进行占位,让用户对真实内容区域有心理预期。App Shell 和骨架屏都是提升首屏体验的绝好妙招。

App Shell 和骨架屏相辅相成,App Shell 显示页面的外框部分,初始内容就用骨架屏来填充,保证主体内容区域不会留白,它的特点是:

  • 在页面加载初期预先渲染内容,提升感官上的体验
  • 一般情况骨架屏和实际内容的结构是类似的,因此之后的切换不会过于突兀。这点和传统的 Loading 动图不同,可以认为是其升级版
  • 只需要简单的 CSS 支持 (涉及图片懒加载可能还需要 JS ),不要求 HTTPS 协议,没有额外的学习和维护成本
  • 如果页面采用组件化开发,每个组件可以根据自身状态定义自身的骨架屏及其切换时机,同时维持了组件之间的独立性。

下图是饿了么web端所展示的效果,为更好的展示效果,我将 network 调整为 slow 3G 的情况。在页面刚进入的过程中,先使用骨架屏进行占位。然后在加载图片时,先使用默认图片进行显示。在真正图片加载好之后,进行图片替换。对用户体验有了很大提升。 骨架屏.gif

# PWA在行业中的优秀实践

# PWA 在爱奇艺登录的应用

在爱奇艺主站的登录页面,是使用 Service Worker 技术来进行网络处理的优化,对常用的 CSSJS 以及图片资源进行缓存,令登录窗口的展现速度明显提升,详见下图:

518e96220c7e8d40b11c7554b0679d04.png

从图中我们可以看出:从 response start 开始的网络响应时间明显降低。更为重要的是,从右侧的“页面加载时间分布”图可以看出,使用 Service Worker 后页面加载时间非常稳定,网络波动对于页面加载造成的影响很小,这对于用户的实际体验会有明显的加分。

# 饿了么多页应用在PWA上面的实践

饿了么在首屏加载上使用 App Shell, 配合骨架屏 以及 服务端渲染 (Server Side Rendering)在首屏加载中有了很大提升。如下图所示,200ms内就已经完成首次渲染,渲染出页面基本的 html 页面。

微信截图_20200117172906.png

同时, 在 Google 开发者网站上也对 http://ele.me 的案例进行了分析。从这个案例分析中,我们可以看到 ele.me PWA 改造的收益如下:

  • 预缓存的页面平均加载时间减少 11.6%
  • 所有页面的平均加载时间减少 6.35%
  • 3G 网络并且是第一次加载时,从页面加载到用户可操作的时间下降到 4.93s

可见,http://ele.me 同样取得了很不错的收益。

# 项目中应用

目前基于公司项目来说,公司内 web 端以 vue 为技术栈开发为主。在 vue 的基础上加入 PWA 技术是可行的,并且在用户体验上也会有一定程度的提升。属于锦上添花的功能。原因如下:

  • vue 为单页应用框架,契合 pwa 的开发建议
  • vue-cli3 脚手架工具中已经支持 pwa 应用
  • pwa 为渐进式应用,用户浏览器不支持的情况下会以普通 web 网页进行访问

# PWA实践方式

  1. 添加 Web App Manifest 文件

添加 Manifest.json 文件配置基本应用信息。并引导用户添加应用的桌面快捷方式。在 pc 端的效果如下(以 vue 官网为例):

微信截图_20200118162000.png

  1. 使用 Service Worker 对部分静态资源文件进行缓存

Service Worker 是浏览器在后端独立于网页主进程运行的脚本,它可以拦截网络请求,可以操作本地缓存等。在项目中可以将常用的图片,css 文件,js 文件,请求常量的接口数据等进行缓存。可以减少请求,提高静态资源加载的速度。

# 参考文章

PWA应用实战
PWA 是否能弥补Web 劣势,带来新一轮大前端技术洗牌?
PWA 在饿了么的实践经验
PWA 技术解析及爱奇艺 PC 端的实践
PWA系列 -- 分享PWA在阿里体系内的实践经验
PWA 推送实践

Last Updated: 1/18/2020, 8:48:52 AM