標籤:

web-pwa

本文主要介紹一個 pwa 很方便的庫,適合在新手上手相關的 pwa 功能。

該庫是應對當前 Google 提出的 PWA 概念而寫的。以鏈式 API 來完成 PWA 相關的操作。

npmgit

(如果感覺閱讀體驗不佳,可以參考 web-pwa)

安裝

npm install web-pwan// 或者使用 yarnnyarn add web-pwan

DEMO

首先說明一下,我們要完成的目標:

  • 註冊 sw

  • 添加 app.js 的緩存

  • 實現推送,並在用戶點擊後關閉,然後聚焦當前頁面

整個代碼如下:

import SW,{Notify,WebCaches} from web-pwa;nnwindow.onload = function(){n SW.register(sw.js);n var tableName = prefetch-cache-v1;n WebCaches.table(tableName).addRow(/app.js)n .then(res=>{n // res: 成功n })n Notify.request() // 請求推送許可權n .then(permission=>{n // 用戶同意n Notify.show(villianhr,Hello Pwa)n .onclick(event=>{n event.close(); // 關閉當前 Notificationn Notify.focus(); // 聚焦窗口n })n })n}n

使用

基本使用可以分為三塊:

  • SW: 主要處理主線程 JS Service Worker 的相關行為。例如:註冊,發送消息等

  • WebCaches: 用來處理 CacheStorage 緩存的相關操作。

  • Notify: 根據 new Notification() 來完成主線程 JS 的消息推送

import SW,{WebCaches,Notify} from web-pwa;n

(重點推薦使用 WebCaches)在內部細節中,處理了兼容性和許可權請求的問題,這裡我們具體落實到場景當中。

SW

SW 原意是 Service Worker。如果大家還不熟悉,推薦可以參考:Service Worker 全面進階。

許可權申請

SW.register(sw.js)n.then(reg=>{nn})n

它返回的是 Promise 對象。

銷毀 Service Worker

SW.unregister().then(res=>{n if(res)console.log(unregisteration, done!);n})n

它返回的是 Promise 對象。

Service Worker 更新

SW.update();n

消息通信

我們了解 Service Worker 是繼承 Web Worker。在 Web Worker 中,我們可以使用 postMessage 進行通信,那麼在 SW(Service Worker)中同樣是可以的。

SW.postMessage(a new message send to Service Worker);n

如果你想接受此次 SW 回復的信息,可以直接加上 Promise 的寫法。

// 接收 SW 回復的信息nSW.postMessage(a new message send to Service Worker)n.then(reply=>{n // doSthn})nn// SW 回複信息nnself.addEventListener(message, function(event){n console.log("SW Received Message: " + event.data);n event.ports[0].postMessage("SW Says Hello back!");n});n

另外,SW 還可以通過 clients 掛載的 postMessage 向 client 發送信息。如果有這種需求,可以直接監聽 message 事件。

SW.onmessage(event=>{n // 接收 SW 發送的消息n // event.datan})n

推送訂閱

當你想要使用 Push 相關的內容時,可以調用 Notify.subscribe(route,key) 方法。如果,你不是很理解 Web Push 的概念,可以參考: Web Push 講解

// 下面的 key 根據自己生成進行替換nSW.subscribe(/subscription,BPLISiRYgXzzLY_-mKahMBdYPeRZU-8bFVzgJMcDuthMxD08v0cEfc9krx6pG5VGOC31oX_QEuOSgU5CYJqpzf0);n

WebCaches

首先這裡有兩個概念,一個是 table(表),一個是 row(行)。每一個網站緩存可以有多個表,這完全取決於你自己的結構。該庫是 one-off 形式,即,不能使用變數名來緩存表。例如:

var table = WebCaches.table(v1);ntable.open(); // 正常執行沒問題nntable.open(); // 第二次使用無效n

後面會介紹一種簡便的方法進行簡寫。

緩存處理主要分為兩塊:

  • table

    • addRow: 添加行記錄

    • delete: 刪除表

    • copy: 複製整個表

    • rename: 重命名整個表

    • open: 打開表

  • row

    • get: 查詢行

    • delete: 刪除行

    • update: 更新行

table

table 本身就是一個函數,構造格式為:

  • table(cachesName): 打開某個具體的表

    • @param cachesName[String]: 具體打開的表名

打開表

構造函數為:

  • open(): 執行打開操作

    • @return: promise

WebCaches.table(demo-v1).open()n.then(cache=>{})n

添加行

向表中添加具體的緩存行,添加方式有三種:

  • addRow(request)

    • @param request: 可以為 url 或者通過 new Request(url) 實例化得來的。

  • addRow([request1,request2,...])

    • @param Array: 裡面就是 url/request 的數組。

  • addRow(request,response)

    • @param request: 和上面一樣,沒啥區別

    • @param response: 需要存儲的結構。一般是通過 new Response(res) 生成,或者直接通過 fetch().then(response=>{}) 獲得的。

重命名/複製表

重命名的格式為:

  • rename(newName)

    • @param newName[String]: 表的新名字

    • @return Promise

WebCaches.table(old-v1).rename(new-v2)n.then(res=>{n // successn})n.catch(err=>{n // failn})n

複製表的格式為:

  • copyTo(targetTable)

    • @param targetTable[String]: 指定的表名

    • @return Promise

// 將 A 表複製給 BnWebCaches.table(A).copyTo(B)n.then(res=>{n // successn})n.catch(err=>{n // failn})n

刪除表

格式為:

  • delete()

  • @return: Promise

WebCaches.table(A).delete()n.then(res=>{n // successn})n.catch(err=>{n // failn})n

row

row 本身也是一個函數:

  • row(request)

    • @param request[Request||String]: 該參數可以為 request,或者 pathname(注意不能帶上 origin)。當為 request 時,是直接匹配對應的行記錄,而為 pathname 時,則是使用 path-to-regexp 的格式,可以匹配多個或者模糊匹配。

// 只匹配 js 文件nnWebCaches.table(tableName).row(/*.js)n.get().then(res=>{n console.log(res);n })n

通過 request 匹配:

var js = new Request(/app.js);nnCaches.table(tableName).row(js)n .get().then(res=>{n console.log(res);n })n

簡寫

如果每次都 WebCaches.table.row 這樣調用,會讓人覺得比較冗長,那麼有沒有什麼好的辦法解決呢?這裡提供了一個工具函數 clone 用來生成可重複使用的對象。

// 提取 tablenvar table_v1 = WebCaches.clone(v1);ntable_v1().open(); // first,OKnntable_v1().open(); // second,OKn

然後,可以提取 row

var table_row = WebCaches.clone(v1,/*.js);nntable_row().get(); // first, OKnntable_row().get(); // second, OKn

刪除行

// 刪除所有 js 文件nWebCaches.table(tableName).row(/*.js)n.delete()n.then(()=>{n // successn})n.catch(err=>{n // failn})n

更新行

fetch(/)n.then(res=>{n// 更新根目錄文件n WebCaches.table(tableName).row(/)n .update(res)n .then(()=>{n WebCaches.table(tableName).row(/).get()n .then(console.log.bind(console))n })n})n

Notify

Notify 提供了 Notification 相關的 API。其主打的是鏈式調用,不需要過多的關注 Notification 內部細節。

許可權申請

notify.request()n.then(permission=>{n // permission === "granted"n // permission === "denied"n // permission === "default"n})n

消息推送

使用消息推送的時候,可以不用嵌套在 request() 裡面,它內部已經做了許可權的處理。

// 純文字版nNotify.show(demo,this is a demo)nn// 帶 IconnNotify.show(demo,this is a demo,demo.png)n

推送後自動關閉

Notify.show(demo,this is a demo)n.hide(3000); // 3s 後自動關閉n

推送點擊

Notify.show(demo,this is a demo)n.onclick(e=>{n e.target.close();n});n

Notify 還提供了其它的事件監聽

  • onclick

  • onclose

  • onshow

  • onerror

上面這些方法都可以進行鏈式調用。

Notify.show(demo,this is a demo)n.onclick(event=>{})n.onclose(event=>{})n.onshow(event=>{})n

用戶點擊推送這一行為,我們可以加上額外的處理,例如,打開頁面,聚焦頁面等。

Notify.show(demo,this is a demo)n.onclick(event=>{n event.target.close();n // 聚焦頁面n Notify.focus();n // 打開新的頁面n Notify.open(https://www.villainhr.com);n})n

License

MIT

Author

  • author: villainhr

  • email: villainthr@gmail.com

推薦閱讀:

PWA 入門: 理解和創建 Service Worker 腳本
Chrome Dev Summit 2017參會筆記
如何看待 Progressive Web Apps 的發展前景?
Progressive Web Apps - Part.3 U4 PWA 特性支持概覽

TAG:PWA |