HTML5-service worker进行缓存控制

讲一下使用service worker做缓存版本控制。

1. 基础

生命周期

installing -> activated -> fech/message

需要关注的生命周期阶段

以下代码以使用indexedDB为例,后面提供使用service worker自带的cache的版本
install:首次缓存

self.addEventListener('install', function(e){
    console.log('SW is installed');
    e.waitUntil(
        caches.open(CACHE_VERSION)
            .then(function(cache){
                const fetchInit = {method: 'GET'};
                fetch('./JJ.mp3', fetchInit)
                .then(function(response){
                    response.arrayBuffer().then(function(buffer){
                        indexedDB.set(buffer, 'Uh.mp3');
                    });
                });
            }));
});

activate:缓存版本更新

self.addEventListener('activate', function(e){
    //Control your cache
});

fetch:拦截请求

self.addEventListener('fetch', function(e){
    console.log('Caught a fetch');

    const url = new URL(e.request.url);
    const fileName = url.split('/')[url.split('/').length-1];
    console.log(fileName);

    indexedDB.get(fileName, function(cacheData){
        if(!cacheData){
            console.log('No cache, sending a new request......');
            fetch(e.request)
                .then(function(response){
                    response.arrayBuffer().then(function(buffer){
                        indexedDB.set(arrayBuffer, fileName);
                        console.log('Cache the file successfully');
                    });
                });
        }else{
            const cacheResponse = new Response(cacheData);
            e.respondWith(cacheResponse);
        }
    });
});

下面代码使用service worker自带的cache,这些数据会存到浏览器cache storage里,使用chrome可以从 Application -> Cache -> Cache Storage中看到

var CACHE_VERSION = 'V1';
var fileURLs = ['https://wximg.gtimg.com/lightmap/cacheTest/ding.mp3'];

console.log('SW is working......');

self.addEventListener('install', function(e){
    console.log('SW is installed');
    e.waitUntil(
        caches.open(CACHE_VERSION)
            .then(function(cache){
                return cache.addAll(fileURLs);
                })
            );
});

self.addEventListener('activate', function(e){
    //control your cache
    event.waitUntil(caches.keys().then(function(cacheNames) {
        return Promise.all(cacheNames.map(function(cacheName) {
            if (cacheName != (SW_VERSION)) {
                return caches.delete(cacheName);
            }
        }));
    }));
});

self.addEventListener('fetch', function(e){
    //console.log(e.request);
    console.log('Catch a fetch event');
    var sourceType = e.request.url.split('.')[e.request.url.split('.').length-1].toLowerCase();
    if(sourceType === 'mp3'){
         e.respondWith(caches.match(e.request).then(function(response){
            if(response){
                return response;
            }else{
                fetch(e.request).then(function(response){
                    caches.open(CACHE_VERSION).then(function(cache){
                        cache.put(e.request, response.clone());
                    }).then(function(){
                        return response;
                    });
                });
            }
        }));
    }else{
        console.log('Fetched file is not mp3', sourceType);
    }
});

3)业务逻辑
用service控制缓存数据(可以用indexedDB或者直接使用service worker自带的cache),install时存入需要静态缓存的数据,fetch时根据url判断数据库中是否有该条数据,决定是发送请求还是直接返回数据库中数据,activate中指定更新策略

2. service worker中遇到的问题

数据库中已经缓存了数据,但是fetch事件不响应,拦截请求不成功

这里写图片描述

一开始以为是fetch()不会触发fetch事件,但是查到:
HTML5-service worker进行缓存控制_第1张图片

那应该是可以触发fetch event的。

然后以为是chrome的bug,不支持fetch事件,因为用window监听fetch事件也不响应。然而firefox也不响应。。。

最后定位问题在于,service worker中,只监听它所控制的scope。我的service worker控制的域是:http://localhost:8080/src/audioCache/,但是发出请求的域是http://localhost:8080/,所以监听不到啊,但是由于文件目录层级原因,我的worker最多只能监听到http://localhost:8080/src/audioCache/。发出请求的域和worker最多可以监听的域不同的原因是,我用webpack启的server,webpack会打包出两个文件,都直接引入index.html中,但是service worker是在一个单独环境运行的啊,它是web worker的一种啊。。。不会被打包啊。。。
这里写图片描述
然而service worker必须在localhost或者https下运行,我必须有一个server,webpack不行的话,我只能用node或者php启动一服务。后来使用php+apache测试成功。

参考链接
https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_API/Using_Service_Workers
https://gist.github.com/inexorabletash/687e7c5914049536f5a3
https://github.com/w3c/ServiceWorker/blob/master/explainer.md
http://w3c.github.io/push-api/
https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch

你可能感兴趣的:(HTML5)