service worker 实践中遇到的问题
1、只有localhost 和 https 支持sw,注册才有效。
2、ios部分手机不支持,安卓支持比较好。但是连了代理的环境下,较新的手机都会注册sw失败,报ssl证书有问题。目前连wifi代理的条件下,safar浏览器能注册并缓存成功。
3、在html上写这么一段代码就能注册sw,其中register第一个参数是指定注册的sw文件,注意sw文件必须在当前页面同级或者更上层。 第二个参数是指定作用的范围,如果浏览器打开过这个html,并且注册这个成功之后,那么scope范围内的其它页面也会受这个sw文件控制了。如果只想当前自己的页面受sw控制,可以直接scope写当前页面的地址。
if ('serviceWorker' in navigator) { window.addEventListener('load', function () { //避免还没load就去加载sw.js文件 浪费首屏显示时间 navigator.serviceWorker.register('/test-sw.js', { scope: './' }).then(function (e) { console.log("Yes, it did.") }).catch(function (err) { console.log("No it didn't. This happened: ", err) }); }); }
4、sw控制页面后,同域下的请求都会走sw的fetch劫持,如果出现http的图片资源就会加载不出来,解决的办法是在sw文件的fetch事件里做判断,只有https的请求才去fetch并且缓存。代码处理如下
5、贴一下整个sw文件的代码
var CACHE_NAME = 'test-sw-7'; var addAll = ['jquery-1.4.2.min.js', 'index.css', 'spark-md5.js'] var util = { fetchPut: function (request, callback) { return fetch(request).then(function (response) { // 跨域的资源直接return if (!response || response.status !== 200 || response.type !== "basic") { return response; } util.putCache(request, response.clone()); typeof callback === 'function' && callback(); return response; }); }, putCache: function (request, resource) { var realUrl = request.url.split('?')[0]; console.log(111111, realUrl) var canCache = false; for (var i = 0; i < addAll.length; i++) { if(realUrl.indexOf(addAll[i]) >= 0) { canCache = true; } } if (request.method === "GET" && canCache ) { console.log('sw缓存', realUrl); caches.open(CACHE_NAME).then(function (cache) { cache.put(request, resource); }); } } }; self.addEventListener('fetch', function(event) { if(event.request.url.indexOf('https') != 0) return console.log('fetch', event.request.url) event.respondWith( caches.match(event.request).then(function(response) { // cache hit if (response) { return response; } return util.fetchPut(event.request.clone()); }) ); }); self.addEventListener('install', function(event) { console.log('install') event.waitUntil(self.skipWaiting()); }); self.addEventListener('activate', function(event) { console.log('activate') Promise.all([ //更新客户端 caches.keys().then(cacheList => { return Promise.all( cacheList.map(cacheName => { console.log('已缓存的CACHE_NAME:', cacheName); if (cacheName !== CACHE_NAME) { console.log('删除掉缓存CACHE_NAME:', cacheName); caches.delete(cacheName); } }) ) }) ]) });