乐趣区

关于javascript:PWA初步实践一

PWA 介绍

PWA(Progressive web apps,渐进式 Web 利用)使用古代的 Web API 以及传统的渐进式加强策略来创立跨平台 Web 应用程序。

PWA 劣势

PWA 是可被发现、易装置、可链接、独立于网络、渐进式、可重用、响应性和安全性

外围指南

  • service workers 数据缓存
  • 增加到主屏幕
  • indexedDB 数据贮存
  • 数据推送

service workers 离线缓存

1、呈现的背景

失落网络连接。即便是世界上最好的 web app,如果下载不了它,也是十分蹩脚的体验。现在尽管曾经有很多种技术去尝试着解决这一问题。而随着离线页面的呈现,一些问题曾经失去了解决。然而,最重要的问题是,依然没有一个好的兼顾机制对资源缓存和自定义的网络申请进行管制。

之前的尝试 — AppCache — 看起来是个不错的办法,因为它能够很容易地指定须要离线缓存的资源。然而,它假设你应用时会遵循诸多规定,如果你不严格遵循这些规定,它会把你的 APP 搞得一团糟。对于 APPCache 的更多详情,请看 Jake Archibald 的文章:Application Cache is a Douchebag.

起初 service workers 呈现了,尽管 Service Worker 的语法比 AppCache 更加简单,然而你能够应用 JavaScript 更加精密地管制 AppCache 的静默行为。有了它,你能够解决目前离线利用的问题,同时也能够做更多的事。Service Worker 能够使你的利用先拜访本地缓存资源,所以在离线状态时,在没有通过网络接管到更多的数据前,仍能够提供最根本的性能


2、应用前筹备

在曾经反对 serivce workers 的浏览器的版本中,很多个性没有默认开启。如果你发现示例代码在以后版本的浏览器中怎么样都无奈失常运行,你可能须要开启一下浏览器的相干配置:

  • Firefox Nightly: 拜访 about:config 并设置 dom.serviceWorkers.enabled 的值为 true; 重启浏览器;
  • Chrome Canary: 拜访 chrome://flags 并开启 experimental-web-platform-features; 重启浏览器 (留神:有些个性在 Chrome 中没有默认凋谢反对);
  • Opera: 拜访 opera://flags 并开启 ServiceWorker 的反对; 重启浏览器
  • Service Workers 网络要求要求必须在 HTTPS 下能力运行。本地开发能够用 localhost


3、根本流程

1、service worker 首先通过 'serviceWorker' in navigator 来判断浏览器是否反对 service worker

    if('serviceWorker' in navigator) {...}

2、service worker URL 通过 serviceWorker.register() 来获取和注册

  navigator.serviceWorker.register('/pwa/serviceWorker.js',{scope: '/pwa/'})
      .then(function () {console.log('registered')
  }).catch(function (e) {console.log(e);
  })

3、如果注册胜利,service worker 就在 ServiceWorkerGlobalScope 环境中运行;这是一个非凡类型的 woker 上下文运行环境,与主运行线程(执行脚本)相独立,同时也没有拜访 DOM 的能力,此时改 js 的 this 指的是 ServiceWorkerGlobalScope 对象而不是window

4、当关上受 service worker 管制的页面后,该页面就会尝试通过 install 办法装置 service worker(开始填充 indexDB 和缓存站点资源)。


    self.addEventListener('install', function (e) {...});

5、当 install 事件的处理程序执行结束后,能够认为 service worker 装置实现了。

6、下一步是激活。当 service worker 装置实现后,会接管到一个激活事件(activate event)。onactivate 主要用途是清理先前版本的 service worker 脚本中应用的资源。

self.addEventListener('activate', function (event) {...})

7、根本流程图


装置和激活:填充你的缓存

install 事件会在注册实现之后触发。install 事件个别是被用来填充你的浏览器的离线缓存能力。为了达成这个目标,咱们应用了 Service Worker 的 新的标志性的存储 API — cache — 一个 service worker 上的全局对象,它使咱们能够存储网络响应发来的资源,并且依据它们的申请来生成 key。这个 API 和浏览器的规范的缓存工作原理很类似,然而是特定你的域的。它会始终长久存在,直到你通知它不再存储,你领有全副的控制权。

留神:  Cache API  并不被每个浏览器反对。(查看 Browser support 局部理解更多信息。)如果你当初就想应用它,能够思考采纳一个 polyfill,比方 Google topeka demo,或者把你的资源存储在 IndexedDB 中。

//install 办法,装置 serviceWorker
self.addEventListener('install', function (e) {self.skipWaiting(); // 告知浏览器间接跳过期待阶段,淘汰过期的 sw.js,间接开始尝试激活新的 service worker
  e.waitUntil(
      // 关上一个新的贮存区域,同时尝试缓存文件
    caches.open('myStore').then(function(cache){
      return cache.addAll([
          '/pwa/index.html',
          '/pwa/index.js',
          '/pwa/gallery/bountyHunters.jpg',
          '/pwa/gallery/myLittleVader.jpg',
          '/pwa/gallery/snowTroopers.jpg',
        ]
      )
    })
  )
});

  1. 这里咱们 新增了一个 install 事件监听器,接着在事件上接了一个ExtendableEvent.waitUntil()  办法——这会确保 Service Worker 不会在 waitUntil() 外面的代码执行结束之前装置实现。
  2. 在 waitUntil() 内,咱们应用了 caches.open() 办法来创立了一个叫做 myStore 的新的缓存,将会是咱们的站点资源缓存的第一个版本。它返回了一个创立缓存的 promise,当它 resolved 的时候,咱们接着会调用在创立的缓存示例上的一个办法  addAll(),这个办法的参数是一个由一组绝对于 origin 的 URL 组成的数组,这些 URL 就是你想缓存的资源的列表。
  3. 如果 promise 被 rejected,装置就会失败,这个 worker 不会做任何事件。这也是能够的,因为你能够修复你的代码,在下次注册产生的时候,又能够进行尝试。
  4. 当装置胜利实现之后,service worker 就会激活。在第一次你的 service worker 注册/激活时,这并不会有什么不同。然而当  service worker 更新 (稍后查看 Updating your service worker 局部) 的时候,就不太一样了。

留神: localStorage 跟  service worker 的 cache 工作原理很相似,然而它是同步的,所以不容许在  service workers 内应用。

留神: IndexedDB 能够在  service worker 内做数据存储。


当遇到被 sw 管制的资源被申请都会触发 fatch 办法
// 每次任何被 service worker 管制的资源被申请到时,都会触发 fetch 事件,这些资源包含了指定的 scope 内的文档,和这些文档内援用的其余任何资源
self.addEventListener('fetch', function (event) {console.log(event.request.url);
  // 劫持 http 响应
  //caches.match(event.request) 容许咱们对网络申请的资源和 cache 里可获取的资源进行匹配,查看是否缓存中有相应的资源。这个匹配通过 url 和 vary header 进行,就像失常的 http 申请一样。event.respondWith(caches.match(event.request).then(function (response) {if(response != undefined) {
      // 缓存中有新的资源;return response
    }else {
      // 缓存中没有新的资源,尝试网络申请去获取新的资源,return fetch(event.request).then(function (response) {
        // 复制一份;// 起因是 response 是一个 Stream,为了让浏览器跟缓存都应用这个 response
        // 必须克隆这个 response,一份到浏览器,一份到缓存中缓存。// 只能被生产一次,想要再次生产,必须 clone 一次
        let resClone = response.clone();
        // 抓取缓存区域
        caches.open('myStore').then(function (cache) {
          // 把数据放到缓存区域中
          cache.put(event.request, resClone);
        })
        return response;
      }).catch(function () {// 尝试申请失败,用 match() 把一些回退的页面作为响应来充当默认资源
        return caches.match('/pwa/gallery/snowTroopers.jpg')
      })
    }
  }))
})

删除旧的缓存

activate: 每个浏览器都对 service worker 能够用的缓存空间有个硬性的限度。浏览器尽力治理磁盘空间,但它可能会删除整个域的缓存。浏览器通常会删除域上面的所有的数据。
传给 waitUntil() 的 promise 会阻塞其余的事件,直到它实现。所以你能够确保你的清理操作会在你的的第一次 fetch 事件之前会实现

// 革除缓存,在第一次 fatch 之前实现,self.addEventListener('activate', function (event) {let cacheWhiteList = ['myStore'];
  console.log(caches)
  event.waitUntil(caches.keys().then(function (keyList) {return Promise.all(keyList.map(function (key) {if(cacheWhiteList.indexOf(key) === -1) {return caches.delete(key)
        }
      }))
    })
  )
})

增加到主屏幕

增加到主屏幕(简称 A2HS)是古代智能手机浏览器中的一项性能,使开发人员能够轻松便捷地将本人喜爱的 Web 应用程序(或网站)的快捷方式增加到主屏幕中,以便他们随后能够通过单点拜访它。

浏览器反对

Mobile Chrome / Android Webview 从 31 版开始反对 A2HS,Opera for Android 从 32 版开始反对,Firefox for Android 从 58 版开始反对。
留神: 电脑上能够实现,手机上没能实现 0..0>

如何应用

线上 demo(在线演示,并查看源代码),

第一次关上如果浏览器反对,会在地址栏的右侧显示 + 的符号,见下图

当点击 + 后会呈现装置的提醒

当点击装置之后就会在你的主屏幕上呈现你想要的程序了,同时程序也被关上了。


Manifest

{
  "background_color": "red",
  "description": "this is demo.",
  "display": "fullscreen",
  "icons": [
    {
      "src": "gallery/icon.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ],
  "name": "one demo",
  "short_name": "Foxes",
  "start_url": "/pwa/index.html"
}
  • background_color:在加载程序之前,启动 app 时的背景色彩,仅用于在从网络或存储介质加载主样式表时改善用户体验
  • discription: string程序的形容。
  • categories:用作目录或商店列表 Web 应用程序的提醒,相似 meta 关键词 .eg"categories": ["books", "education", "medical"]
  • display:指定应如何显示利用。为了使它看起来像一个独特的应用程序(而不仅仅是网页),您应该抉择一个值,例如fullscreen(基本不显示任何 UI)或独立standalone(十分类似,然而零碎级 UI 元素(例如状态栏)可能是可见的)。
  • icons:指定在不同地位(例如,在工作切换器上或更重要的是在主屏幕上)示意应用程序时浏览器应用的图标。
  • name/short_name:这些字段提供了在不同地位示意应用程序时要显示的应用程序名称。name提供残缺的利用名称。short_name当没有足够的空间显示全名时,提供一个缩写名称。如果您的应用程序名称特地长,建议您同时提供两者。
  • start_url:提供启动增加到主屏幕应用程序时应加载的资源的门路。请留神,这必须是一个假相网站主页的相对路径,绝对于 manifest 的 url。另外,请留神,Chrome 在显示装置标语之前须要这样做,而 Firefox 在显示“含 + 号的 home”图标时并不需要它。
  • 更多具体字段

### 帮忙链接

  • pwa 实际
  • MDN

这次咱们介绍了 service worker 的缓存跟如何把程序增加到桌面,剩下的会在下一篇更新,欢送小伙伴来观光

退出移动版