看掘金社区半年的时间,第一次自己动手把自己平时学习的心得发表出来,看了一些关于pwa的入门教程文章,感觉还是有点云里雾里,终于在b站上面找到了百度lavas项目分享的视频,感觉有点感觉了。
效果入下


1:创建sw.js文件
self.addEventListener('fetch', function(event) {
console.log('request:' +event.request.url )
})
2:在页面load事件完成之后注册serviceWorker,(在load事件完成之后注册sw是为了避免进程阻塞)
window.addEventListener('load', function(event) {
if('serviceWorker' in window.navigator) {
// {scope:'/'} 指的是在根目录的时候注册不写也是默认根目录
navigator.serviceWorker.register('sw.js',{scope:'/'}).then(function(registeration){
console.log('service worker register success with scope', registeration.scope)
})
// 控制权发生改变,提醒用户数据更新了
navigator.serviceWorker.oncontrollerchange = function(event) {
console.log('页面已经更新')
alert('页面已经更新')
}
// 兼容用户断网之后的情况
if(!navigator.onLine) {
alert('网络已经断开,内容可能已过期')
window.addEventListener('online',function(evnet) {
alert('网络已连接,刷新获取最新信息')
})
}
}
})
调试工具中的功能介绍 application->serviceWorker
- offline 指的是模拟浏览器断网的状态
- updata to reload 每次都是重新安装注册sw
- bypass for network 不经过sw的代理 只从网络请求中拿数据
- 清除sw的缓存
-
- clear storage->clear site data 直接一键清除sw的缓存数据
3:sw下配置 确定缓存的数据列表
let CACHE_VERSION = 0; //缓存版本号
let CACHE_NAME = 'cache_v' + CACHE_VERSION; // 缓存名称
let CACHE_URLS = [
'/',
'/api/movies',
'/js/main.js',
'/js/render.js',
'/css/main.css',
'/img/logo.png'
]
4:sw下配置 在什么时候去缓存这些数据
注意:// 缓存的文件只要有一个失败所有都不能用
// sw文件会事先注册监听install文件
// 当sw注册成功之后install时间就会触发
function preCache() {
// 使用cache.openapi开辟和sw相对性的缓存区 存储在cache storage中
return caches.open(CACHE_NAME)
.then(function(cache) {
return cache.addAll(CACHE_URLS)
})
}
function clearCache() {
return caches.keys().then(keys =>{
keys.forEach(key => {
// 如果key不等于当前的cachename就删除掉
if(key !== CACHE_NAME) {
caches.delete(key);
}
})
})
}
function saveToCache (req, res) {
return caches
.open(CACHE_NAME)
.then(cache => cache.put(req, res))
}
function fetchAndCache(req) {
return fetch(req).then(function(res){
// res 是一个流需要复制一份
saveToCache(req, res.clone());
return res;
})
}
self.addEventListener("install", function(event) {
event.waitUntil( // cache.open也是一个promise链,因此需要waitUntil事件来控制这个缓存阶段的流程
// skipWaiting 让上一个serviceWorker返回
preCache().then(self.skipWaiting)
)
})
// 在activate触发时会删除旧的缓存
self.addEventListener('activate', function(event) {
event.waitUntil(
// 清除缓存同时获得控制权
Promise.all([
clearCache(),
self.clients.claim()//在激活的过程里,需要调用clients.claim方法来让正在被激活的sw获得对cliam的完全控制权,
// 首次加载页面的时候 ,页面是没有被sw控制的,只有重新刷新页面才能不要重新刷新页面,就可是sw获得请求拦截等的页面控制权
])
)
})
// fetch请求结束并且失败了才拿缓存中的数据
self.addEventListener('fetch', function(event) {
let url = new URL(event.request.url);
console.log('origin:' + origin,self.origin,'请求地址:'+event.request.url );// 如果不是同源数据就不拿sw的数据 走cnd拿数据
if(url.origin !== self.origin) {
return ;
}
// 处理缓存接口数据太旧的问题
if(event.request.url.includes('/api/movies')) {
event.respondWith(
//fetchAndCache :先请求网络数据,失败了才走缓存数据,有网的情况下请求保存到本地 如果失败了 拿缓存
fetchAndCache(event.request).catch(
function() {
return caches.match(event.request);
}
)
)
return;
}
event.respondWith( //event.respondWith 等待其中的promise参数resolve之后才会内容给页面
// 正常先从网络中请求数据,如果请求失败就从本地缓存中拿数据
fetch(event.request).catch(function() {
return caches.match(event.request);
})
)
})