20180308_PWA

PWA初级

what is pwa ?

  • PWA,全称Progressive Web Apps是Google提出的用前沿的Web技术为网页提供APP般使用体验的一系列方案。

prepare

  • 首先准备好http-server、ngrok

  • 需要的基础html及css

  • manifest.json文件

manifest.json

  • 该文件主要是让PWA应用呗添加到主屏幕时,定义应用的名称,图标icon等信息

showtime😋

我们添加必要的html代码和引入css、manifest.json,然后加入index.js来注册serviceWorker。
https://www.w3.org/TR/service-workers-1/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (navigator.serviceWorker != null) {
navigator.serviceWorker.register('sw.js')
.then(function(registration) {
console.log('Registered events at scope: ', registration.scope);
});
}

在serviceWorker中会用到一些全局变量:
>self:表示Service Worker作用域,也是全局变量

>caches:表示缓存

>skipWaiting:表示强制当前处在waiting状态的脚本进入activate状态

>clients:表示Service Worker接管的页面

缓存

定义缓存

var cacheStorageKey = ‘minimal-pwa-1’ //cache-key
var cacheList = [ //cache-list
‘/‘,
“index.html”,
“index.css”,
“./image/clear.png”
]

借助Service Worker写缓存

1
2
3
4
5
6
7
8
9
self.addEventListener('install', function(e) {
e.waitUntil(
caches.open(cacheStorageKey).then(function(cache) {
return cache.addAll(cacheList)
}).then(function() {
return self.skipWaiting()
})
)
})

调用self.skipWaiting()可以在页面更新过程中,新的Service Worker脚本能立即激活和生效

动态缓存

网页抓取资源过程中,在Service Worker可以捕获fetch事件,可以自定义资源的响应请求

1
2
3
4
5
6
7
8
9
10
11

self.addEventListener('fetch', function(e) {
e.respondWith(
caches.match(e.request).then(function(response) {
if (response != null) {
return response
}
return fetch(e.request.url)
})
)
})

例:我们可以通过fetch事件来处理获取资源异常的case,从而增强程序完整性和健壮性、可用性

更新静态资源

缓存的资源随着版本的更新会过期,所以会根据缓存的字符串名称清除旧缓存

1
2
3
4
5
6
7
8
9
10
11
12
self.addEventListener('activate', function(e) {
e.waitUntil(
caches.keys().then(function(keyList){
return Promise.all(keyList.map(function(key){
if (key !== cacheStorageKey) {
return caches.delete(key)
}
}))
})
)
return self.clients.claim()
})

在新安装的Service Worker中通过调用self.clients.claim()取得页面的控制权,保证使用最新缓存。旧sw脚本也会停止。
确保在每次修改了 service worker 后修改 cacheName,这能确保你永远能够从缓存中获得到最新版本的文件。过一段时间清理一下缓存删除掉没用的数据也是很重要的。

我就想看看它长什么样子?😏

1
2
http-server -c-1
ngrok http 8080

浏览器打开http://localhost:8080

页面更新

页面被缓存之后,需要适当处理缓存失败时页面失效的更新。被缓存的资源是无法发起请求来判断是否被更新了,只有sw.js会自动根据http缓存机制尝试去判断应用是否被更新。
所以页面发生修改时,要同步修改sw.js文件,保证缓存名称也修改了。

1
2
<h3>Revision 2</h3>
let cacheStorageKey = 'minimal-pwa-2'

然后重新打开页面,这个时候渲染的页面依然是旧的,不过从devtools里看到sw.js被安装和激活。之后再次打开可以网页版本为2

PWA进阶版本

何为进阶版本,那就是看起来比较牛逼的版本。

App Shell

从缓存中加载app shell

*Service workers 可以截获 Progressive Web App 发起的请求并从缓存中返回响应。这意味着我们能够 决定如何来处理这些请求,以及决定哪些网络响应能够成为我们的缓存。

*从内至外,caches.match() 从网络请求触发的 fetch 事件中得到请求内容,并判断请求的资源是 否存在于缓存中。然后以缓存中的内容作为响应,或者使用 fetch 函数来加载资源(如果缓存中没有该资源)。 response 最后通过 e.respondWith() 返回给 Web 页面。

Push

😋 Push API提供Web应用消息推送能力,需要获取用户权限。

第一种姿势-本地模拟

1
2
3
4
5
6
7
8
9
default: unknown
granted:已授权
let notification = new Notification({})
denied:未授权
Notification.permission === 'default' || Notification.permission !== 'denied'
Notification.requestPermission(permission => {
permission === 'granted' &&
(let notification = new Notification({}))
})

https://developer.mozilla.org/en-US/docs/Web/API/Notification/permission

第二种姿势-firebase 😌鉴权登录有毒啊啊啊啊啊

https://console.firebase.google.com/project/schacker-pwa/notification
https://developers.google.com/web/fundamentals/engage-and-retain/push-notifications/subscribing-a-user

对于 Push Notification,一是因为 Push API 还处于 Editor Draft 的状态,二是目前浏览器与推送服务的互相支持都还不够成熟:Android 上的 Chrome(与其它基于 Blink 的浏览器)目前只支持基于 Google 私有的 GCM/FCM 的通知推送,只有 Firefox 已经实现了成在由 IETF 进行标准化的 Web 推送协议(Web Push Protocol)。

不过,如果你已经在使用 Google 的云服务(比如 Firebase),并且主要面向的是海外用户,那么在 Web 应用上支持基于 GCM/FCM 的推送通知并不是一件费力的事情。
对于
对于firebase推送这块,可以自己搭建服务器来调用Google SDK提供的API接口实现自定义推送,包括自己的推送后台

https://developers.google.com/web/fundamentals/engage-and-retain/push-notifications/sending-messages-with-web-push-libraries

有待挖掘

使用技术 ep:
Ajax、响应式设计、JavaScript 框架、ECMAScript Next、CSS Next、Houdini、Indexed DB、Device APIs、Web Bluetooth、Web Socket、Web Payment、孵化中的 Background Sync API、Streams、WebVR