PWA——下一代的web应用模型

PWA——下一代的web应用模型

    • 什么是PWA
    • PWA为什么会出现
    • 如何判断一个web应用是PWA
  • 核心功能
    • Service-Workers
    • 注册service worker
    • service worker中的常用事件
    • Manifest
    • 清单文件
    • 添加到主屏
    • Push&Notification
    • 通知API——请求授权
    • 推送
  • 发展趋势
    • 优势
    • 劣势

概述

不知道从什么时候开始,当我们在浏览网页时,页面会出现一个弹窗,询问我们是否要将此网页保存到本地,如果我们选择了确定,在设备的主屏上就会出现一个新的app,而它就是我们刚才浏览的网页。这种app我们并没有从应用商店去下载,但是我们可以像使用app一样去使用它,也可以像卸载其他app一样去将它卸载,那么这究竟是个什么东西呢,它就是这篇文章的主角——PWA。

什么是PWA

PWA是Progressive Web App的简写,中文名称为渐进式web应用。它是Google 在2016年提出的概念,2017年落地的web技术,一种在移动端利用提供的标准化框架,在网页应用中实现和原生应用相近的用户体验的渐进式网页应用。PWA不单指一种技术,你也可以将其理解为一种思想和概念,目的就是对标原生app,将Web网站通过一系列的Web技术去优化它,提升其安全性,性能,流畅性,用户体验等各方面指标,最后达到用户就像在用app一样的感觉。

PWA为什么会出现

说到app,我们就不得不提起native app即原生app,现在非常主流的移动端应用。原生app使用起来会很流畅,性能好,安全性也可以很高,这是它很显著的优势。但是缺点呢,也很明显,比如:

1. 开发成本很昂贵
2. 软件上线,版本更新都需要发布到不同的商店,并通过审核

这对开发人员来说是比较麻烦的事情。
而对于用户来说,有些APP可能使用频率特别少,但还是不得不去商店中下载庞大的安装包,或者可能一段时间不使用以后,随着版本的更新,也不得不去重新更新并安装。

PWA则完美地避免了这些问题。

如何判断一个web应用是PWA

要判断一个web应用是否是PWA,可以从以下几个方面去考虑:

1. 可发现的—— 内容可以通过搜索引擎发现。
2. 可安装—— 可以出现在设备的主屏幕。
3. 可链接—— 你可以简单地通过一个URL来分享它。 
4. 独立于网络——它可以在离线状态或者是在网速很差的情况下运行。
5. 渐进式—— 它在老版本的浏览器仍旧可以使用,在新版本的浏览器上可以使用全部功能。
6. 可重用—— 无论何时有新的内容它都可以发送通知。
7. 响应性—— 它在任何具有屏幕和浏览器的设备上可以正常使用——包括手机,平板电脑,笔记本,电视,冰箱,等。
8. 安全—— 在你和应用之间的连接是安全的,可以阻止第三方访问你的敏感数据。

当然,在安装方式上PWA应用与原生app有很大的不同,但是在实际使用上,与原生应用的差距非常小,对于用户来说,几乎是无感的。

核心功能

Service-Workers

Service Workers是浏览器和网络之间的虚拟代理,运行在一个与页面的 JavaScript 主线程独立的线程上,并且没有对 DOM 结构的任何访问权限,并且可以在不同的上下文之间发送和接收信息。 您可分配给 Service Worker 一些任务,并使用基于 Promise 的方法在任务完成时收到结果。他们不仅仅提供离线功能,还提供包括处理通知,在单独的线程上执行繁重的计算等。Service workers 非常强大,因为他们可以控制网络请求,修改网络请求,返回缓存的自定义响应,或合成响应。因为它们非常强大,所以 Service Workers 只能在安全的上下文中执行(即 HTTPS )。

注册service worker

if ('serviceWorker' in navigator) {
      // 浏览器支持SW
      // Service Worker 的注册路径决定了其 scope 默认作用页面的范围。如果存放在网站的根路径下,则将会收到该网站的所有 fetch 事件。如果希望改变它的作用域,可在第二个参数设置 scope 范围
      navigator.serviceWorker.register('serviceWorker.js').then(function (registration) {
     
        console.log('ServiceWorker注册成功: ', registration.scope);
      }).catch(function (err) {
     
        console.log('ServiceWorker注册失败: ', err);
      });
    }

注册完成后,serviceWorker.js 文件会自动下载,然后安装,最后激活。

service worker中的常用事件

1. install
var cacheName = 'hello-pwa';

// install 事件,它发生在浏览器安装并注册 Service Worker 时  
self.addEventListener('install', event => {
     
  // event.waitUtil 用于在安装成功之前执行一些预装逻辑,但是建议只做一些轻量级和非常重要资源的缓存,减少安装失败的概率,安装成功后 ServiceWorker 状态会从 installing 变为 installed
  event.waitUntil(
    caches.open(cacheName)
      .then(cache => cache.addAll(
        [
          '/',  // 这个一定要包含整个目录,不然无法离线浏览
          './images/cat2.jpg',
          './index.html',
          './style.css'
        ]
        // 如果所有的文件都成功缓存了,便会安装完成。如果任何文件下载失败了,那么安装过程也会随之失败。   
      )).then(() => self.skipWaiting())
  );
});

service worker会等到 waitUntil 里面的代码执行完毕之后才开始安装,它返回一个promise。
caches 是一个特殊的 CacheStorage 对象,它能在Service Worker指定的范围内提供数据存储的能力。

2. fetch 

每次当我们的应用发起一个http请求时,我们还有一个fetch 事件可以使用。这个事件对我们来说非常有用,它允许我们拦截请求并对请求作出自定义的响应。

// 为 fetch 事件添加一个事件监听器,service worker将从缓存中请求所需的数据,从而提供离线应用功能
self.addEventListener('fetch', function (e) {
     
  event.respondWith(
    // 使用 caches.match() 函数来检查传入的请求 URL 是否匹配当前缓存中存在的任何内容,如果存在的话,返回缓存的资源;如果资源并不存在于缓存当中,通过网络来获取资源,并将资源存储到缓存中。
    caches.match(e.request).then(function (r) {
     
      return r || fetch(e.request).then(function (response) {
     
        return caches.open(cacheName).then(function (cache) {
     
          cache.put(e.request, response.clone());
          return response;
        });
      });
    })
  );
});

Manifest

为了成为可安装网站,需要下列事情就位:

  • 一份网页清单,填好正确的字段
  • 网站的域必须是安全(HTTPS)的
  • 一个本设备上代表应用的图标
  • 一个注册好的service worker,可以让应用离线工作(这仅对于安卓设备上的Chrome浏览器是必需的)

清单文件

清单文件通常位于网页应用的根目录,包含一些有用的信息,比如应用的标题,在一个移动OS上显示的代表该应用的不同大小的图标(例如,主屏图标)的路径,和用于加载或启动画面的背景颜色。这些信息是浏览器在安装web应用时和在主屏上显示应用需要的,这些信息是以JSON的形式列出来的。

{
     
  "name": "Minimal PWA", //网站应用的全名
  "short_name": "PWA Demo", // 显示在主屏上的短名
  "description": "The app that helps you understand PWA",  //一两句话解释你的应用的用途
  "display": "standalone",  // 应用的显示方式:可以是全屏,独立,最小ui或者浏览器
  "start_url": "/",  //应用启动的index文档
  "theme_color": "#313131", // ui的主题色,这是操作系统使用的
  "background_color": "#313131", // 背景色,用于安装程序时和启动应用时
  "icons": [
    {
     
      "src": "icon/lowres.webp",
      "sizes": "48x48", 
      "type": "image/webp" 
    },
    {
     
      "src": "icon/lowres",
      "sizes": "48x48"
    },
    {
     
      "src": "icon/hd_hi.ico",
      "sizes": "72x72 96x96 128x128 256x256"
    },
    {
     
      "src": "icon/hd_hi.svg",
      "sizes": "72x72"
    }
  ] //一串图标信息——源URL,大小和类型,确保包含一些图标,这样有一个最适合用户设备的图标可以被选中
}

一份网页清单最少需要name和一个图标 (带有 src, size 和 type)。description, short_name, 和start_url最好要提供。

扩展以下,过去有一些常用的扩展名用于清单:manifest.webapp 在Firefox OS应用清单中很流行,许多人使用manifest.json作为网页清单因为内容是JSON格式的。但是,.webmanifest 扩展名是在W3C清单规范中显示指定的,建议使用清单文件使用.webmanifest作为后缀 。

添加到主屏

“添加到主屏”是移动浏览器实现的一个特性,它利用网页清单中的信息来在设备主屏上显示应用图标和文字。当用户使用一个支持的移动浏览器访问一个PWA时,会显示一个弹框表示可以安装这个应用,用户确认之后应用就被安装到主屏了,用户可以立刻启动并使用应用。在一些浏览器中,可以通过清单信息产生一个启动画面,当PWA启动时显示,图标、主题和背景色用于创建这个启动画面。

在ios上和android手机上打开vue的官网,可以将其添加到设备主屏:

  • ios

PWA——下一代的web应用模型_第1张图片PWA——下一代的web应用模型_第2张图片

  • android

PWA——下一代的web应用模型_第3张图片PWA——下一代的web应用模型_第4张图片

Push&Notification

Push&Notification即推送和通知,通过推送API和通知API来实现。

  • 推送可以实现从服务端推送新的内容而不需要客户端发起请求,它是由应用的service worker来实现的。通知功能则可以通过service worker来向用户展示一些新的信息,或者至少提醒用户应用已经更新了某些功能。
  • 这些工作是在浏览器外部实现的,跟service worker一样,所以即使应用被隐藏到后台甚至应用已经被关闭了,我们仍然能够推送更新或者推送通知给用户。
  • 推送API和通知API可以独立工作,也可以结合到一起使用。

通知API——请求授权

当用户确定接收通知,我们的应用就可以获得推送通知的功能。用户的授权的结果有三种,default,granted 或者denied,当用户没有做出选择的时候,授权结果会返回defalut,另外两种结果分别是用户选择了授权或者拒绝授权。一旦用户选择授权,这个授权结果对通知API和推送API两者都有效。

var button = document.getElementById("notifications");
console.log(button);
button.addEventListener('click', function (e) {
     

  Notification.requestPermission().then(function (result) {
     
    if (result === 'granted') {
     
      // randomNotification();
      console.log('授权');
    }
  });
});

推送

推送比通知要复杂一些,我们需要从服务端订阅一个服务,之后服务端会推送数据到客户端应用。应用的Service Worker将会接收到从服务端推送的数据,这些数据可以用来做通知推送,或者实现其他的需求,这个技术还处在非常初级的阶段。
为了接收到推送的消息,你需要有一个service worker,在service worker 内部,存在一个消息推送服务订阅机制。

registration.pushManager.getSubscription() .then( /* ... */ );

一旦用户订阅服务,他们就能接收到服务器推送的通知。为了能够接收到推送的消息,我们需要在Service Worker文件里面监听push事件。

self.addEventListener('push', function(e) {
      /* ... */ });

这个技术还处在非常初级的阶段,从服务端的角度来看,出于安全的目的,这整个过程必须使用非对称加密技术进行加密。而VAPID可以为你的应用提供一层额外的安全保护。

发展趋势

既然谈到PWA的发展趋势,就不得不说说它的优势和劣势了。

优势

  • 无需安装,无需下载,只要你输入网址访问一次,然后将其添加到设备桌面就可以持续使用。
  • 发布不需要提交到app商店审核,更新迭代版本不需要审核
  • 现有的web网页都能通过改进成为PWA, 能很快的转型,上线,实现业务、获取流量
  • 不需要开发Android和IOS两套不同的版本

劣势

  • 浏览器对技术支持还不够全面, 不是每一款游览器都能100%的支持所有PWA
  • 需要通过第三方库才能调用底层硬件(如摄像头)
  • PWA现在还没那么火,国内一些手机生产上在Android系统上做了手脚,似乎屏蔽了PWA

PWA作为一个2016年才落地的新技术,经过四年的发展,基于 Chromium 的浏览器 Chrome 和 Opera 已经完全支持 PWA 了,随着 iOS 11.3 的发布,iOS正式开始支持PWA,Windows Edge 也支持PWA了。越来越多的游览器大厂,相继的对PWA做出了支持和优化,想必PWA的时代即将到来。

关于PWA,你怎么看呢?

你可能感兴趣的:(前端,web)