PWA的探索与应用

本文由云+社区发表html

PWA(Progressive Web App)起源背景

传统的Web网页存在如下几个问题:web

  • 进入一个页面必需要记住它的url或者加入书签,入口不便捷;
  • 没网络就没响应,不具有离线能力;
  • 不像APP同样能进行消息推送。

Native app:chrome

  • 开发成本高
  • 软件上线须要审核
  • 即便使用频率不高,想使用一个app必须先下载安装

PWA概念的提出

2016 年Google I/O 大会上提出一个 Next Web Generation 的概念。PWA是在传统Web应用的基础上,结合Manifest和service worker,完善Web应用的一些能力,好比:json

  • 添加至主屏幕,点击主屏幕图标能够实现启动动画以及隐藏地址栏
  • 实现离线缓存功能,即便用户手机没有网络,依然可使用一些离线功能
  • 消息推送

PWA技术点

Web App Manifest

Web App Manifest 技术实现了将PWA网页应用 添加至桌面的功能,但该项技术目前仍处于实验性阶段,各浏览器支持度不高小程序

imgimage.pngsegmentfault

PWA 站点部署的 manifest.json文件知足如下条件时会自动显示横幅:微信小程序

- short\\_name (主屏幕显示)
- name (安装横幅显示)
- icons (必须包含一个 mime 类型为 image/png 的图标声明)
- start\\_url (应用启动地址)
- display (必须为 standalone 或 fullscreen)
- 站点注册 Service Worker。
- 站点支持 HTTPS 访问。
- 同一浏览器中站点至少被访问两次,间隔至少为 5 分钟。

Service Worker

​ PWA应用的离线体验、按期的后台同步以及推送通知等功能的实现依赖于Service Worker技术,下图为目前SW技术的支持度。浏览器

img

SW具备如下特征:缓存

  • 一个独立的 worker 线程,独立于当前网页进程,有本身独立的 worker context。
  • 一旦被 install,就永远存在,除非被手动 unregister
  • 用到的时候能够直接唤醒,不用的时候自动睡眠
  • 离线内容开发者可控
  • 能向客户端推送消息
  • 不能直接操做 DOM
  • 必须在 HTTPS 环境下才能工做
  • 异步实现,内部大都是经过 Promise 实现

Service Worker生命周期

img

  • installing:这个状态发生在 SW 注册以后开始安装,install 事件回调中执行skipWaiting()方法表示强制当前处在 waiting 状态的 Service Worker 进入 activate 状态。
  • installed:SW已经完成了安装,等待其余的 SW 线程被关闭。
  • activating:在这个状态下清除其余的worker 以及关联缓存的旧缓存资源,等待新的 SW线程被激活。在 activate 事件回调中执行self.clients.claim()方法表示取得页面的控制权, 这样以后打开页面都会使用版本更新的缓存。旧的 Service Worker 脚本再也不控制着页面,以后会被中止。
  • activated:在这个状态能够处理功能性的事件 fetch (请求)、sync (后台同步)、push (推送)。
  • 废弃状态 ( redundant ):这个状态表示一个 Service Worker 的生命周期结束。

Service Worker 支持的事件

img

  • install:Service Worker 安装成功后被触发的事件, 在事件处理函数中能够添加须要缓存的文件
  • activate:当 Service Worker 安装完成后并进入激活状态,会触发 activate 事件。经过监听 activate 事件你能够作一些预处理,如对旧版本的更新、对无用缓存的清理等。
  • message:Service Worker 运行于独立 context 中,没法直接访问当前页面主线程的 DOM 等信息,可是经过 postMessage API,能够实现他们之间的消息传递,这样主线程就能够接受 Service Worker 的指令操做 DOM。
  • fetch :当浏览器在当前指定的 scope 下发起请求时,会触发 fetch 事件,并获得传有 response 参数的回调函数。fetch 事件特别重要,由于它可以定义你的缓存策略。也就是说,你能够决定什么时候使用缓存数据,什么时候使用网络请求来的数据。
  • push:push 事件是为推送准备的。经过 PUSH API,当订阅了推送服务后,可使用推送方式唤醒 Service Worker 以响应来自系统消息传递服务的消息,即便用户已经关闭了页面。
  • sync:sync 事件由 background sync (后台同步)发出。background sync 是 Google 配合 SW 推出的 API,用于为 Service Worker 提供一个能够实现注册和监听同步处理的方法。但它还不在 W3C Web API 标准中。在 Chrome 中这也只是一个实验性功能,须要访问 chrome://flags/#enable-experimental-web-platform-features ,开启该功能,而后重启生效。Sync 事件容许延迟网络任务,直到用户链接上网络,它实现的功能一般被称为后台同步。这对于在离线模式下,确保用户启动的任何有网络依赖的任务,最终都将在网络再次可用时达到其预期目的,是很是有用的。

Service Worker 的工做原理

Service Worker是基于注册、安装、激活等步骤微信

注册

if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
    navigator.serviceWorker.register('/jslearning/sw.js') // 默认做用域为jslearning下,也能够经过设置scope参数进行设置
        .then(function (registration) {
            // 注册成功
            console.log('ServiceWorker registration successful with scope: ', registration.scope);
        })
        .catch(function (err) {
            // 注册失败:(
            console.log('ServiceWorker registration failed: ', err);
        });
});
}

安装

this.addEventListener('install', function(event) {
  console.log('V1 installing…');
  //须要缓存的重要的高优先级资源
  var vipUrlsToPrefetch = [
'./index.html'
  ];
  //次重要的资源
  var urlsToPrefetch = [
'./icon.png'
  ];
  event.waitUntil(
caches.open(OFFLINE_CACHE_NAME).then(function(cache) {
  //urlsToPrefetch非重要资源,即便有资源加载失败也不影响Service Worker安装
  cache.addAll(urlsToPrefetch);
  //vipUrlsToPrefetch中资源所有请求成功,Service Worker安装事件才顺利完成,能够进入激活事件
  return cache.addAll(vipUrlsToPrefetch);
})
  );      
});

激活

//Service Worker激活事件
this.addEventListener('activate', function(event) {
  //在激活事件中清除非当前版本的缓存避免用户存储空间急剧膨胀
  event.waitUntil(caches.keys().then(function(cacheNames) {
console.log('V1 activate');
return Promise.all(cacheNames.map(function(cacheName) {
    if (cacheName !== OFFLINE_CACHE_NAME) {
      if(cacheName.indexOf(OFFLINE_CACHE_PREFIX) != -1) {
        return caches.delete(cacheName);
      }
    }
}));
  }));
});

Service Worker更新

  • 若是线程的字节与已有的SW线程字节不一样,浏览器则考虑更新SW线程。
  • 更新的SW线程与现有SW线程一块儿启动,并获取本身的 install 事件。
  • 若是新工做SW线程出现不正常状态代码(例如,404)、解析失败,在执行中引起错误或在安装期间被拒,则系统将舍弃新工做线程,但当前工做线程仍处于活动状态。
  • 安装成功后,更新的工做线程将 wait,直到现有工做线程控制0个客户端。
  • self.skipWaiting() 可跳过等待状况,这意味着sw线程在安装完后当即激活。

Service Worker缓存策略

​ Service Worker缓存策略大部分在fetch与install时间中定义,对于某些固定不变的静态资源,能够在Service Worker初次安装的install事件中将其缓存,但资源过大或者网络不佳都会形成资源并未所有下载成功而致使Service Worker安装被中断安装失败。SW主要有如下几类缓存策略:

  • 不影响安装的资源预缓存
  • 渐进式缓存
  • 仅使用缓存、仅使用网络
  • 缓存优先 、网络优先
// 渐进式缓存
var addToCache = function(req) {   
  return fetch(req.clone()).then(function(resp) {   
    var cacheResp = resp.clone();
    if (!resp.ok) {
      return resp;
    }
    caches.open(OFFLINE_CACHE_NAME).then(function(cache) {
      cache.put(req.clone(), cacheResp);
    });
    return resp;
  });
};
 
this.addEventListener('fetch', function(event)  {
  event.respondWith(
     caches.open(OFFLINE_CACHE_NAME).then(function(cache) {
          return cache.match(event.request);
      }).then(function(response) {
        if (response) {
            return response;
        } else {
            return addToCache(event.request);
        }
    })
  ); 
});

PWA应用能够经过开发者工具中的Application进行查看调试,以下图所示:

img

PWA优缺点总结

优势

  • 能够将app的快捷方式放置到桌面上,全屏运行,与原生app无异
  • 可以在网络差和断网条件下
  • 推送消息的能力
  • 快速响应用户指令

缺点

  • 支持率不高
  • Chrome在安卓移动端上的占有率很低
  • 依赖的GCM服务在国内没法使用
  • 微信小程序的竞争

PWA应用

  • Lavas 是一套基于 Vue 的 PWA 解决方案,可以帮助开发者快速搭建 PWA 应用
  • 新浪微博
  • 饿了么
  • Instagram
  • Twitter
  • Offline Wikipedia
  • Spotlight
  • ...

参考文献

此文已由做者受权腾讯云+社区在各渠道发布

获取更多新鲜技术干货,能够关注咱们腾讯云技术社区-云加社区官方号及知乎机构号

相关文章
相关标签/搜索