如果想要跟着文章内容一起实践,可以在这里下载到所需的全部代码。 记得切换到manifest
分支,因为本篇内容,是基于上一篇的最终代码进行相应的开发与升级。毕竟我们的最终目标是将这个普通的“图书搜索”demo升级为PWA。
self
是Service Worker中一个特殊的全局变量,类似于我们最常见的window
对象。self
引用了当前这个Service Worker。cacheFiles
中我们列出了所有的静态资源依赖。注意其中的'/'
,由于根路径也可以访问我们的应用,因此不要忘了将其也缓存下来。当Service Worker install时,我们就会通过caches.open()
与cache.addAll()
方法将资源缓存起来。这里我们给缓存起了一个cacheName
,这个值会成为这些缓存的key。caches
是一个全局变量,通过它我们可以操作Cache相关接口。Cache 接口提供缓存的 Request / Response 对象对的存储机制。Cache 接口像 workers 一样, 是暴露在 window 作用域下的。尽管它被定义在 service worker 的标准中, 但是它不必一定要配合 service worker 使用。——MDN
fetch
方法向服务端发起请求,并返回请求结果给浏览器fetch
事件会监听所有浏览器的请求。e.respondWith()
方法接受Promise作为参数,通过它让Service Worker向浏览器返回数据。caches.match(e.request)
则可以查看当前的请求是否有一份本地缓存:如果有缓存,则直接向浏览器返回cache
;否则Service Worker会向后端服务发起一个fetch(e.request)
的请求,并将请求结果返回给浏览器。cacheName
。由于浏览器判断sw.js是否更新是通过字节方式,因此修改cacheName
会重新触发install并缓存资源。此外,在activate事件中,我们需要检查cacheName
是否变化,如果变化则表示有了新的缓存资源,原有缓存需要删除。fetch
事件里进行API数据的缓存apiCacheName
。在fetch
事件中,我们首先通过对比当前请求与cacheRequestUrls
来判断是否是需要缓存的XHR请求数据,如果是的话,就会使用fetch
方法向后端发起请求。fetch.then
中我们以请求的URL为key,向cache中更新了一份当前请求所返回数据的缓存:cache.put(e.request.url, response.clone())
。这里使用.clone()
方法拷贝一份响应数据,这样我们就可以对响应缓存进行各类操作而不用担心原响应信息被修改了。getApiDataRemote()
以供调用,同时将其改造为了Promise。为了节省篇幅,我部分的代码比较简单,就不单独贴出了。caches
变量来访问到缓存对象的。令人高兴的是,在我们的前端应用中,也仍然可以通过caches
来访问缓存。当然,为了保证渐进可用,我们需要先进行判断'caches' in window
。为了代码的统一,我将获取该请求的缓存数据也封装成了一个Promise方法:queryBook()
方法中,我们会请求后端数据,然后渲染页面;而现在,我们加上基于缓存的渲染:getApiDataFromCache(url).then
返回缓存数据,则使用它先进行渲染。而当remotePromise
的数据返回时,与cacheData
进行比对,只有在数据不一致时需要重新渲染页面(注意这里为了简便,粗略地使用了JSON.stringify()
方法进行对象间的比较)。这么做有两个优势:最后声明一下,文中的代码作为demo,主要是用于了解与学习PWA技术原理,可能会存在一些不完善的地方,因此,不建议直接使用到生产环境。