作者|极链科技视频++前端团队
收拾|包

前端技术近年来发展迅速,包括PWA,全称Progressive Web APP,是2016年Google I/O大会上提出的下一代Web的一个概念。PWA是专门为处理手机Web开发而提出的。它可以结合web和app各自的优势:实现渐进和离线加载逼近app的交互,可以实时更新、推送和安装,让我们在使用web应用时,体验可以像原生App一样。特别是很多人认为PWA是新技术,其实不是。它是众多Web技术的集合,其中最核心的技术是“服务工作者”,我们后面会讲到。
目前我们使用的是Web应用,像很多国内的spa,一般是打开一个页面就发起请求获取数据,离线时一般不可用。PWA旨在改善Web的体验,将网络的优势与应用的优势结合起来,给用户更好的体验。PWA具有以下特征:
即使在不稳定的网络环境中也很可靠,可以立即加载并显示。快速响应用户交互。用流畅的动画快速响应。像粘性设备上的原生应用程序一样,它具有逼真的用户体验,用户也可以将其添加到桌面上。渐进式适合使用任何浏览器的用户,因为它的核心是增量增强。适配可以以任何形式使用:桌面设备、移动设备等。保护HTTPS,防止窥探,保护内容不被篡改。可以发现,由于W3C清单和服务注册的范围,搜索引擎可以找到它并将其识别为“应用程序”。安装者可以去app store下载,也可以直接将应用添加到主屏幕保留使用。链接可以通过url地址共享应用程序,无需复杂的安装。我们选几个点来说明一下:
可安装的
它指的是像原生应用程序一样在设备的主屏幕上留下图标。为了实现这个特性,我们首先需要提供Web应用程序清单。manifest是一个json文件,它描述了应用程序的图标如何在主屏幕上显示,以及点击后跳转到什么页面。我们可以直接在html中引用它“”,其格式如下:
几个属性代表以下含义:
Start_url设置跳转的地址。
图标让我们设置页面的图标。
Background_color设置背景色,应用程序启动后将立即使用,并且将一直保留在屏幕上,直到网络应用程序首次呈现。
主题颜色设置主题颜色。
设定是否开始显示。
这里的显示设置web应用程序是否隐藏浏览器的UI。当display的值为“独立”时,web应用程序隐藏浏览器的UI。当display的值为“browser”时,将正常显示。
对于manifest.json中字段更具体的含义,感兴趣的同学可以去Google Developer的文档中探究一下。
这是刁很有特点的一点:可以离线使用,即即使没有网络环境也可以打开应用。这个强大功能背后的大人物是:服务人员。
服务工作者实际上是一个脚本。通常,我们的缓存是session、localStorage和cachestore。PWA通过Service worker访问cachestore,实现缓存和离线开发。
下面简单说一下服务人员的概念。通常情况下,主Javascript线程运行在浏览器的加载页面上,而Service worker作为一个独立的线程,可以理解为默默无闻地运行在浏览器后面的线程。
因为这个特性,Service worker无论如何都不会阻塞我们的主线程,也就是说我们的浏览器页面不会卡住等等。使用Service worker的时候要注意,我们使用的协议必须是https。当然,如果我们想获得一个用于本地开发的https,这是一个很头疼的问题。幸运的是,Service worker允许localhost是localhost或者127.0.0.1也可以运行。
让我们看一看。如何注册服务人员?

首先我们要判断目前使用的浏览器是否支持Service worker,这样才能继续使用。如果是这样,在页面加载时注册位于/sw.js的服务工作者,并查看下面的代码:
每次页面加载成功,都会调用register方法,浏览器会判断服务工作线程是否注册,并进行相应的处理。
register方法的scope参数是可选的,用于指定您希望服务工作人员控制的内容的子目录。本演示中的服务工作者文件位于根域中,这意味着服务工作者的范围将是整个源代码。
关于服务工作者更详细的介绍,感兴趣的同学可以参考MDN文档。
是的,服务人员也有生命周期。详细介绍请参考下图:
说了这么多,我们开发者怎么知道一个网页是否具备PWA的某些特性呢?
我们可以通过Google开发工具找到Audits面板,可以检测页面是否具有PWA的特征:
让我们来看一个简单的演示,看看PWA在离线时仍然可以快速加载应用程序。
首先,我们会直接显示正在加载中的loading,保证用户打开网页时能立刻看到,让用户知道此时页面正在加载中:
此时,我们取消html页面中引用的js的注释,加载我们编写的虚假数据:
那么如何实现缓存呢?也就是说,数据是在离线环境中加载的。当网络环境设置为脱机时,无法加载页面:
在这里,它应该应用于上面提到的Service worker服务线程。
让我们首先检查浏览器是否支持服务人员:
如果浏览器支持,将注册服务工作线程,在用户第一次打开页面时触发安装事件,从而缓存所需内容。
下图是核心代码,实现了真正的离线缓存:
首先,我们需要通过caches.open打开缓存并提供一个缓存名称。提供一个缓存名可以让我们对文件进行版本控制,或者将数据从App Shell中分离出来,这样我们就可以很容易地更新一些数据,而不会影响其他数据。
我们在安装侦听器下添加激活事件侦听器,因为激活事件将在服务工作器启动时被触发。图中activate事件中的代码可以确保在文件发生变化时更新缓存。
最后,我们需要从缓存中提取我们需要的内容,即以下代码:

Caches.match将从内向外评估触发抓取事件的网络请求,并检查它是否在缓存中。然后,它用缓存的版本进行响应,或者从网络上获取一个副本,响应通过e.respondWith返回到web页面
现在让我们看看当我们离线时页面是否会加载。
如图所示,在离线网络环境中,我们的应用程序成功加载。
这个小演示到此为止!
目前Progressive Web App还处于起步阶段,在国内的普及程度还不够。但背后的技术和前端的全新定位也不容忽视。或许会像AJAX十年前那样改变前端的生态。


