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 |