一个 PWA 应用首先是一个网页, 可以通过 Web 技术编写出一个网页应用. 随后添加上 App Manifest 和 Service Worker 来实现 PWA 的安装和离线等功能。
简单的
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<title>点聚合</title>
<link rel="manifest" href="manifest.json" />
<link rel="stylesheet" href="index.css">
<script>
console.log(navigator)
if(navigator.serviceWorker != null) {
console.log(111)
navigator.serviceWorker.register('sw.js')
.then((registration) => {
console.log('registration events at scope ', registration.scope)
})
} else {
console.log(222)
}
</script>
<style>
html, body, #container {
height: 100%;
width: 100%;
}
.input-card {
width: 25rem;
}
.input-card .btn {
width: 7rem;
margin-right: .7rem;
}
.input-card .btn:last-child {
margin-right: 0;
}
</style>
</head>
<body>
<div id="container" class="map" tabindex="0">
<h1>pwd 简单实现 F12 大家调试模式</h1>
<h2></h2>
</div>
</body>
</html>
</html>
sw.js
/*
self: 表示 Service Worker 作用域, 也是全局变量
caches: 表示缓存
skipWaiting: 表示强制当前处在 waiting 状态的脚本进入 activate 状态
clients: 表示 Service Worker 接管的页面
*/
const cacheStorageKey = "minimal-pwa-03"
const cacheList = [
'/',
"index.html",
"index.css",
"icon.png"
]
// 借助 Service Worker, 可以在注册完成安装 Service Worker 时, 抓取资源写入缓存:
self.addEventListener("install", e => {
e.waitUntil(
caches.open(cacheStorageKey)
.then(cache => cache.addAll(cacheList))
.then(() => self.skipWaiting)
)
})
// 调用 self.skipWaiting() 方法是为了在页面更新的过程当中, 新的 Service Worker 脚本能立即激活和生效
// 网页抓取资源的过程中, 在 Service Worker 可以捕获到 fetch 事件, 可以编写代码决定如何响应资源的请求:
self.addEventListener('fetch', function(e) {
e.respondWith(
caches.match(e.request).then(function(response) {
console.log('动态缓存处理', response)
if (response != null) {
return response
}
return fetch(e.request.url)
})
)
})
// 更新静态资源
self.addEventListener('activate', (e) => {
e.waitUntil(
Promise.all(
caches.filter(name => {
return name !== cacheStorageKey
}).map(name => {
return caches.delete(name)
})
).then(() => self.clients.claim())
)
})
// 在新安装的 Service Worker 中通过调用 self.clients.claim() 取得页面的控制权, 这样之后打开页面都会使用版本更新的缓存。旧的 Service Worker 脚本不再控制着页面之后会被停止
源码地址
https://gitee.com/liuyuquancode/pwa-demo.git
缓存的资源随着版本的更新会过期, 所以会根据缓存的字符串名称(这里变量为 cacheStorageKey, 值用了 "minimal-pwa-1")清除旧缓存, 可以遍历所有的缓存名称逐一判断决决定是否清除(备注: 简化的写法, Promise.all 中 return undefined 可能出错, 见评论):