资讯专栏INFORMATION COLUMN

web-pwa

vibiu / 886人阅读

摘要:根据来完成主线程的消息推送重点推荐使用在内部细节中,处理了兼容性和权限请求的问题,这里我们具体落实到场景当中。

本文主要介绍一个 pwa 很方便的库,适合在新手上手相关的 pwa 功能。

该库是应对当前 Google 提出的 PWA 概念而写的。以链式 API 来完成 PWA 相关的操作。

(如果感觉阅读体验不佳,可以参考 web-pwa)

安装
npm install web-pwa
// 或者使用 yarn
yarn add web-pwa
DEMO

首先说明一下,我们要完成的目标:

注册 sw

添加 app.js 的缓存

实现推送,并在用户点击后关闭,然后聚焦当前页面

整个代码如下:

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

window.onload = function(){
    SW.register("sw.js");
    var tableName = "prefetch-cache-v1";
    WebCaches.table(tableName).addRow("/app.js")
    .then(res=>{
        // res: 成功
    })
    Notify.request() // 请求推送权限
    .then(permission=>{
        // 用户同意
        Notify.show("villianhr","Hello Pwa")
        .onclick(event=>{
            event.close(); // 关闭当前 Notification
            Notify.focus(); // 聚焦窗口
        })
    })
}
使用

基本使用可以分为三块:

SW: 主要处理主线程 JS Service Worker 的相关行为。例如:注册,发送消息等

WebCaches: 用来处理 CacheStorage 缓存的相关操作。

Notify: 根据 new Notification() 来完成主线程 JS 的消息推送

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

(重点推荐使用 WebCaches)
在内部细节中,处理了兼容性和权限请求的问题,这里我们具体落实到场景当中。

SW

SW 原意是 Service Worker。如果大家还不熟悉,推荐可以参考:Service Worker 全面进阶。

权限申请
SW.register("sw.js")
.then(reg=>{

})

它返回的是 Promise 对象。

销毁 Service Worker
SW.unregister().then(res=>{
    if(res)console.log("unregisteration, done!");
})

它返回的是 Promise 对象。

Service Worker 更新
SW.update();
消息通信

我们了解 Service Worker 是继承 Web Worker。在 Web Worker 中,我们可以使用 postMessage 进行通信,那么在 SW(Service Worker)中同样是可以的。

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

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

// 接收 SW 回复的信息
SW.postMessage("a new message send to Service Worker")
.then(reply=>{
    // doSth
})

// SW 回复信息

self.addEventListener("message", function(event){
    console.log("SW Received Message: " + event.data);
    event.ports[0].postMessage("SW Says "Hello back!"");
});

另外,SW 还可以通过 clients 挂载的 postMessage 向 client 发送信息。如果有这种需求,可以直接监听 message 事件。

SW.onmessage(event=>{
    // 接收 SW 发送的消息
    // event.data
})
推送订阅

当你想要使用 Push 相关的内容时,可以调用 Notify.subscribe(route,key) 方法。如果,你不是很理解 Web Push 的概念,可以参考: Web Push 讲解

// 下面的 key 根据自己生成进行替换
SW.subscribe("/subscription","BPLISiRYgXzzLY_-mKahMBdYPeRZU-8bFVzgJMcDuthMxD08v0cEfc9krx6pG5VGOC31oX_QEuOSgU5CYJqpzf0");
WebCaches

首先这里有两个概念,一个是 table(表),一个是 row(行)。每一个网站缓存可以有多个表,这完全取决于你自己的结构。该库是 one-off 形式,即,不能使用变量名来缓存表。例如:

var table = WebCaches.table("v1");
table.open(); // 正常执行没问题

table.open(); // 第二次使用无效

后面会介绍一种简便的方法进行简写。

缓存处理主要分为两块:

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()
.then(cache=>{})
添加行

向表中添加具体的缓存行,添加方式有三种:

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")
.then(res=>{
    // success
})
.catch(err=>{
    // fail
})

复制表的格式为:

copyTo(targetTable)

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

@return Promise

// 将 A 表复制给 B
WebCaches.table("A").copyTo("B")
.then(res=>{
    // success
})
.catch(err=>{
    // fail
})
删除表

格式为:

delete()

@return: Promise

WebCaches.table("A").delete()
.then(res=>{
    // success
})
.catch(err=>{
    // fail
})
row

row 本身也是一个函数:

row(request)

@param request[Request||String]: 该参数可以为 request,或者 pathname(注意不能带上 origin)。当为 request 时,是直接匹配对应的行记录,而为 pathname 时,则是使用 path-to-regexp 的格式,可以匹配多个或者模糊匹配。

// 只匹配 js 文件

WebCaches.table(tableName).row("/*.js")
.get().then(res=>{
  console.log(res);
  })

通过 request 匹配:

var js = new Request("/app.js");

Caches.table(tableName).row(js)
    .get().then(res=>{
      console.log(res);
    })
简写

如果每次都 WebCaches.table.row 这样调用,会让人觉得比较冗长,那么有没有什么好的办法解决呢?这里提供了一个工具函数 clone 用来生成可重复使用的对象。

// 提取 table
var table_v1 = WebCaches.clone("v1");
table_v1().open(); // first,OK

table_v1().open(); // second,OK

然后,可以提取 row

var table_row = WebCaches.clone("v1","/*.js");

table_row().get(); // first, OK

table_row().get(); // second, OK
删除行
// 删除所有 js 文件
WebCaches.table(tableName).row("/*.js")
.delete()
.then(()=>{
    // success
})
.catch(err=>{
    // fail
})
更新行
fetch("/")
.then(res=>{
// 更新根目录文件
  WebCaches.table(tableName).row("/")
  .update(res)
  .then(()=>{
    WebCaches.table(tableName).row("/").get()
    .then(console.log.bind(console))
  })
})
Notify

Notify 提供了 Notification 相关的 API。其主打的是链式调用,不需要过多的关注 Notification 内部细节。

权限申请
notify.request()
.then(permission=>{
    // permission === "granted"
    // permission === "denied"
    // permission === "default"
})
消息推送

使用消息推送的时候,可以不用嵌套在 request() 里面,它内部已经做了权限的处理。

// 纯文字版
Notify.show("demo","this is a demo")

// 带 Icon
Notify.show("demo","this is a demo","demo.png")
推送后自动关闭
Notify.show("demo","this is a demo")
.hide(3000); // 3s 后自动关闭
推送点击
Notify.show("demo","this is a demo")
.onclick(e=>{
    e.target.close();
});

Notify 还提供了其它的事件监听

onclick

onclose

onshow

onerror

上面这些方法都可以进行链式调用。

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

用户点击推送这一行为,我们可以加上额外的处理,例如,打开页面,聚焦页面等。

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

MIT

Author

author: villainhr

email: villainthr@gmail.com

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/61832.html

相关文章

发表评论

0条评论

vibiu

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<