初次学习,水平甚浅,这篇文章主要作为知识的汇总巩固,如果有错误的地方还请自由指出
pwa是什么
Progressive Web App
- 可以网页离线可访问(Service Worker)
- 可以像原生应用一样添加到桌面(manifest)
- 可以推送消息(Notifacation,Push)
manifest
manifest只是一些json的配置,用来写一些将网页添加到桌面需要设置
这是一个自动生成manifest的网站,能将app icon压缩成各种大小适配不同屏幕
你只需将manifest像这样引入网页即可:
...
<link rel="manifest" href="./manifest.json">
</head>
[图片上传失败...(image-47b6fd-1550053020802)]
[图片上传失败...(image-606f2c-1550053020802)]
如果在安卓手机上,需要在chrome上才可以添加到屏幕
Service Worker
Service worker是一个注册在指定源和路径下的事件驱动worker。它采用JavaScript控制关联的页面或者网站,拦截并修改访问和资源请求,细粒度地缓存资源。你可以完全控制应用在特定情形(最常见的情形是网络不可用)下的表现。
如果你要了解Service Worker的话,你首先要了解:
不然会十分难理解service worker的内容。
service worker 主要由cache和worker组成。
cache就是存储sw(service worker)缓存下来的资源的地方。
worker就是js用来处理比较复杂的计算而创造的,一个新的线程,在这里监听sw的事件(sw是事件驱动的),对网络请求进行一系列操作,来实现离线访问页面,推送消息的目的。
service worker的生命周期
[图片上传失败...(image-4f8fca-1550053020802)]
- install 安装
- installed 安装成功
- activating 激活
- activated 激活成功
- redundant 废弃
要使用sw,首先要在网页上注册sw:
if ('serviceWorker' in navigator) {
window.addEventListener('DOMContentLoaded', () => {
navigator.serviceWorker.register('./serviceWorker.js').then(registration => {
console.log('支持sw: ' + registration.scope)
}).catch(err => {
console.log('sw 注册失败: ' + err)
})
})
}
install
注册时,sw就会进入到install流程中,在sw.js文件中:
const OFFLINE_CACHE_PREFIX = 'offline_page_'
const CACHE_VERSION = 'v1.0'
const OFFLINE_CACHE_NAME = OFFLINE_CACHE_PREFIX + CACHE_VERSION
this.addEventListener('install', event => {
let urlsToPreFetch = [
'./pwa.html',
'./style/css.css',
'./manifest.json'
]
event.waitUntil(
caches.open(OFFLINE_CACHE_NAME).then(
cache => {
return cache.addAll(urlsToPreFetch)
}
)
)
})
OFFLINE_CACHE_PREFIX
是cache的名字
CACHE_VERSION
是cache的版本号
OFFLINE_CACHE_NAME
是某一个cache的名称
urlsToPreFetch
定义了在安装阶段就要预先存储到cache中的资源
event.waitUntil
是一个只用内部方法完成了才会继续的方法,这样使得只有安装成功了预先需要存储的资源,install才能成功,否则sw则会redundant。
cache.addAll
类似于fetch加上cache.put,先请求资源,再将资源缓存。
activate
sw安装成功后,进入激活状态,可以在这里清理旧版本的缓存
this.addEventListener('activate', event => {
event.waitUntil(caches.keys().then(cacheNames => {
return Promise.all(cacheNames.map(cacheName => {
if (cacheName !== OFFLINE_CACHE_NAME) {
if (cacheName.indexOf(OFFLINE_CACHE_PREFIX) !== -1) {
return caches.delete(cacheName)
}
}
}))
}))
})
fetch
监听fetch来判断是否需要从网络请求资源或者直接从缓存获取即可
this.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(response => {
if (response) {
console.log('use cache: '+response)
return response
}
let fetchRequest = event.request.clone()
return fetch(fetchRequest)
.then(response => {
console.log('send fetch')
let responseToClone = response.clone()
caches.open(OFFLINE_CACHE_NAME).then(cache => {
cache.put(event.request, responseToClone)
})
return response
})
.catch(() => {
return caches.open(OFFLINE_CACHE_NAME).then(
cache => {
return cache.match(event.request.url)
}
)
})
})
)
})
在这里,首先在cache中match是否有请求的资源已经存在,如果存在,则直接返回缓存的资源,如果不存在,就通过fetch去获取资源,并将资源缓存。
这里将event.request clone是由于event.request是只能使用一次的流,在先前的caches.match中已经被使用过了,已经不能再次使用,所以需要克隆。
后面的responseToClone则是cahce.put使用了response之后,response将无法访问,也就无法返回给event.respondWith,所以将response克隆,用备份来代替response添加到cache中。
sw.js的更新
注册了sw的网页每一次打开,都会去请求sw.js,如果sw文件有更新,则会出发新的install事件,但不会立马替代原本的sw文件,新的 Service Worker 完成安装后会进入 waiting 状态。直到所有已打开的页面都关闭,旧的 Service Worker 自动停止,新的 Service Worker 才会在接下来打开的页面里生效。
如果你想立马更新sw文件,则你需要在install兼容中加入skipWaiting
this.addEventListener('install', event => {
self.skipWaiting()
let urlsToPreFetch = [
'./pwa.html',
'./style/css.css',
'./manifest.json'
]
event.waitUntil(
caches.open(OFFLINE_CACHE_NAME).then(
cache => {
return cache.addAll(urlsToPreFetch)
}
)
)
})
![](https://img.haomeiwen.com/i8790335/c058397448aa2bab.png)
或者你也可以在chrome的devtool中点击skipWaiting来跳过等待。
消息推送
似乎由于土啬的原因,google的许多推送服务不能用,不知为何我的ssr也爆炸了,所以大家自行研究。
在chrome中调试pwa
![](https://img.haomeiwen.com/i8790335/1a55ff40b73b3e9c.png)
offline可以测试离线环境下网页的加载
Update on reload 则是自动更新sw文件
Cache Storage中可以查看cache中的资源
网友评论