上一篇说过的manifest离线缓存方法虽然被所有主流浏览器的最新版本所支持,但终究还是在web标准中被废弃了,firefox在控制台会提醒使用Service Worker缓存替代。
但其实Service Worker还远远没有被普遍支持,仅chrome、firefox和opera的新版本支持,Edge和safari的支持尚在开发中,而且Service Worker要求必须在https网站上使用。所以实际上,在相当长的时间内manifest缓存会一直被各大浏览器支持,不会被轻易删除。新标准的普及需要时间,旧标准的完全退出更需要时间,这个时间,可能长于大部分网站的生命周期……
但我还是先试了一下Service Worker,方法同样很简单,第一步先注册Service Worker,类似于manifest方法中在html元素内添加清单文件,只不过这里是在页面注册一个js文件,引入以下js代码即可。
if ('serviceWorker' in navigator) { window.addEventListener('load', function() { navigator.serviceWorker.register('/qifu/sw.js').then(function(registration) { console.log('ServiceWorker registration successful with scope: ', registration.scope); }).catch(function(err) { console.log('ServiceWorker registration failed: ', err); }); }); }
注册的这个js文件所在的路径会影响Service Worker的作用域,它在哪个目录下,作用域就包含哪个目录。比如“/qifu/sw.js”就会导致作用域是/qifu/及其下属目录,而放在根目录的话,作用域就是全站。
下面是注册的Service Worker文件内容(/qifu/sw.js)。
var CACHE_NAME = 'qifu'; //缓存名称 var urlsToCache = [ '/qifu/', 'style.css', 'script.js' ]; //要缓存的资源url self.addEventListener('install', function(event) { event.waitUntil( caches.open(CACHE_NAME) .then(function(cache) { console.log('Opened cache'); return cache.addAll(urlsToCache); }) ); }); //初始化安装,缓存上面列出的资源 self.addEventListener('fetch', function(event) { event.respondWith( caches.match(event.request) .then(function(response) { if (response) { return response; } return fetch(event.request); } ) ); }); //拦截所有请求,缓存过则直接返回
首先是安装Service Worker,也就是初始化,告诉浏览器先缓存好哪些内容;然后Service Worker就拦截所有请求,有缓存就直接返回缓存内容。初始化只有第一次以及Service Worker文件有更新后才会触发,否则会被自动跳过。
Service Worker缓存之所以被推出用来替代manifest缓存,一个很重要的原因就是更灵活。比如即使初始化时没有缓存某些文件,也可以在后续用到时自动缓存(具体代码本文不再列出,只比上述代码多几行),而不像manifest一样必须逐一列出要缓存的内容,还不允许通配符CACHE。
由于目前浏览器对于Service Worker的支持尚不广泛,可以同时保留manifest缓存,如果支持的话,浏览器检测到两者并存会自动使用Service Worker。
类似于manifest缓存,每次打开浏览器,会使用缓存的数据,然后浏览器默默查看Service Worker文件有没有更新,只要有哪怕一个字节的变化,就会重新缓存,新内容同样是下次访问生效。(大部分网站可能都为js文件设置了HTTP缓存,目前浏览器在检查Service Worker文件更新时会遵守http header里面设置的缓存时间,但最长24小时,如果超过了这一数值,浏览器会重新下载Service Worker的js文件。)
如果更新后的Service Worker定义了新的缓存名称,通常希望删掉旧的缓存,可以用下面的代码:
self.addEventListener('activate', function(event) { var cacheWhitelist = ['not-delete-cache-a', 'not-delete-cache-b']; //上面是不要删除的缓存名,其余全部删除 event.waitUntil( caches.keys().then(function(cacheNames) { return Promise.all( cacheNames.map(function(cacheName) { if (cacheWhitelist.indexOf(cacheName) === -1) { return caches.delete(cacheName); } }) ); }) ); });
好了,就这么简单。
钦佩懂技术的🙂
我要是懂,绝对自己开发个博客平台,绝对的
我是略懂,还没那本事……不过我猜博客简单的用不了一天就可以,复杂的像WP,那就难了。
就服这个缓存~我至今不会搞。
不会大多是因为你不想……
术语太专业
难得有人说我专业
看见代码先嘿嘿
我就看看不说话。。[/发呆]
技术太专业看不懂,只能路过了
不需要的技术,一般不需要懂
现在的网站速度都还可以啊,只要不是太多的多媒体元素。普通网页本身是很小的,在网速面前不值一提了。
的确,再加上cdn,速度都不在话下。这个功能目的是让有特殊需求的网页离线可用,缓存只是途径。
如果浏览器支持只要这么几行代码就能本地缓存?
是的,很简单,可以参考qifu.me/hello/的源码……
这个不错 哈哈 缓存后速度飞快了
关键是没网也能飞
这样的方法也很不错。
对于博客网站来说,缓存大多不必用这种方式。