学习service worker之一:两种更新

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zgrbsbf/article/details/79964314

下面把学习的过程中遇到的问题和感悟记录如下:

我用的webstorm

一个页面,引入了index.js,index.js的代码如下:

navigator.serviceWorker
    .register('./sw.js')
    .then(function (reg) {
        console.log('Service Worker Registered');
    });

setTimeout(() => {
    const img = new Image();
    img.src = 'img/limochou.jpg';
    document.body.appendChild(img);
}, 1000);
setTimeout(() => {
    const img = new Image();
    img.src = 'img/zhaomin.jpg';
    document.body.appendChild(img);
}, 1000);

sw的代码如下:

let pre = '/your-first-pwapp-master/mytest/';
let toCaches = [
    pre + 'index.html',
    pre + 'index.js',
    pre + 'img/zhaomin.jpg',
    pre + 'img/xiaolongnv.jpg',
];
self.addEventListener('install', event => {
    console.log('install');
    event.waitUntil(
        caches.open('one')
            .then(cache => cache.addAll(toCaches)) //还可以有返回值啊,我都不知道
            .then(ok => console.log('add all ok'), e => console.log(e))
    );
});

self.addEventListener('activate', event => {
    console.log('one now ready to handle fetches!');
});

self.addEventListener('fetch', event => {
    console.log(`fetch`, event.request.url);
    caches.keys().then(ks => console.log(ks));
    if (event.request.url.includes('zhaomin')) {
        event.respondWith(caches.match(pre + 'img/xiaolongnv.jpg'));
    } else {
        event.respondWith(
            caches.match(event.request).then(function (response) {
                if (response) {
                    console.log('有', event.request.url);
                    return response;
                } else {
                    console.log('没有', event.request.url);
                    return fetch(event.request);
                }
            })
        );
    }
});

插曲:

在我本地使用的是webstorm访问,
http://localhost:63342/your-first-pwapp-master/mytest/index.html?_ijt=u8bf0oqpq91pfok9oi8tv6id2
但是当我勾选了offline之后,不能访问了,但是我已经离线了啊,service worker应该是支持离线的啊,为什么呢,后来我找到原因了:
这里写图片描述
就是因为用webstorm打开的时候它默认带上了参数,把参数去掉就可以了:
http://localhost:63342/your-first-pwapp-master/mytest/index.html

到目前为止,看到的情况是这样子的:
1. 第一次打开链接会看到下面的页面:
这里写图片描述
2. 刷新页面会看到:
这里写图片描述
第一次打开看到李莫愁和赵敏,刷新之后用小龙女替换了赵敏。

更新

想做到不关闭浏览器,也不关闭标签页面,通过刷新来更新

我先更新了index.js,加入了一句话:

alert('我更新了');

也修改了sw.js:

// caches.open('one')
caches.open('two')

还有:

self.addEventListener('activate', event => {
    console.log('two now ready to handle fetches!');
});

这里写图片描述
http://localhost:63342/your-first-pwapp-master/mytest/index.html
继续刷新页面,发现不管刷新多少次都不会有alert,点击上图中的update,skipWaiting都不行,勾选了update on reload 也不行,直到我点击了unregister之后才可以,不过这个可以只有一次有效,再次刷新还是走的旧的,为什么会这样呢,我看了看cache storage里面的缓存:
这里写图片描述
这里写图片描述
可以看到这个时候two里面缓存的index.js还是旧的,和one里面的是一样的。那么如果想让新的代码起作用怎么办?

尝试1:install之后删除别的缓存

self.addEventListener('install', event => {
    console.log('install');
    event.waitUntil(
        Promise.all([
            // caches.open('one')
            caches.open('two')
                .then(cache => cache.addAll(toCaches)) //还可以有返回值啊,我都不知道
                .then(ok => console.log('add all ok'), e => console.log(e))
            ,
            // 清理旧版本
            caches.keys().then(function (cacheList) {
                return Promise.all(
                    cacheList.map(function (cacheName) {
                        if (cacheName !== 'two') {
                            console.log('清理',cacheName);
                            return caches.delete(cacheName);
                        }
                    })
                );
            })
        ])
    );
});

然后刷新两次,第一次刷新变化如下:
这里写图片描述
从上图可以看出缓存one已经被清理了,但是新的sw还处于waiting状态,
第二次刷新之后,结果如下:
这里写图片描述
新的sw还没有activate,但是alert已经弹出来了!
我尝试点击skipWaiting,打印出来了:

two now ready to handle fetches!

这是不是说明新的sw即使没有activate,也能接管页面发出的请求,因为真正起作用的是缓存呢?

尝试2:在activate里面删除旧的缓存,

self.addEventListener('activate', event => {
    console.log('two now ready to handle fetches!');
    event.waitUntil(
        Promise.all([
            // 清理旧版本
            caches.keys().then(function (cacheList) {
                return Promise.all(
                    cacheList.map(function (cacheName) {
                        if (cacheName !== 'two') {
                            console.log('清理',cacheName);
                            return caches.delete(cacheName);
                        }
                    })
                );
            })
        ])
    );
});

第一次刷新结果如下:
这里写图片描述
新的sw安装了,还没有activate
第二次刷新刷新还是旧的,得点击skipWaiting才能让新的sw activate,才能弹出alert。
为了不用点击skipWaiting,在install事件中加入:

self.skipWaiting();

这样的话第二次刷新就弹出alert了。

不过尝试1中的实现可以少写一行代码。。。

参考文献:
1. https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle?hl=zh-cn#clientsclaim
2. https://mdn.mozillademos.org/files/12636/sw-lifecycle.png
3. https://lavas.baidu.com/pwa/offline-and-cache-loading/service-worker/how-to-use-service-worker#service-worker-%E7%89%88%E6%9C%AC%E6%9B%B4%E6%96%B0

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页