cordova 实现网页缓存_Service Worker与缓存

本文介绍了如何利用ServiceWorker(SW)实现高效的缓存策略,避免依赖HTTP缓存。通过在SW的install阶段避免使用HTTP缓存,确保资源的最新版本。同时,讲解了内存缓存MemoryCache和推送缓存Push“Cache”的工作原理,以及它们在浏览器缓存机制中的角色。此外,推荐使用sw-precache自动化生成SW脚本,简化缓存管理。
摘要由CSDN通过智能技术生成

前言

随着Service Worker(以下简称SW)的普及和规范,我们可以使用SW提供的缓存接口替代HTTP缓存。当然SW的功能是强大的,除了缓存功能,还能够使用它来实现离线、数据同步、后台编译等等。

8c0d0784829292c96c5c2f105502fb29.png

应用

一个标配版的sw缓存工代代码应该有以下的片段:

const version = '2';self.addEventListener('install', event => { event.waitUntil( caches.open(`static-${version}`) .then(cache => cache.addAll([ '/styles.css', '/script.js' ])) );});self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request) .then(response => response || fetch(event.request)) );});

首先你要明白的前提是,网络请求首先到达的是SW脚本中,如果未命中再转发给HTTP缓存。

这段代码的意思是,在SW的install阶段我们将script.js和styles.css放入缓存中;而在请求发起的fetch阶段,通过资源的URL去缓存内查找匹配,成功后立刻返回,否则走正常的网络请求流程。

但你有没有考虑过,在install阶段的资源内容是哪里来的?仍然是从HTTP缓存中。这样SW缓存机制又有可能随着HTTP缓存陷入了之前所说的版本不一致的困境中。

既然我们借助SW重写了缓存机制,所以也不想再受牵制于旧的HTTP缓存。解决办法是让SW中的请求必须向服务端验证:

self.addEventListener('install', event => { event.waitUntil( caches.open(`static-${version}`) .then(cache => cache.addAll([ new Request('/styles.css', { cache: 'no-cache' }), new Request('/script.js', { cache: 'no-cache' }) ])) );});

目前并非所有的浏览器都支持cache选项的配置。但这个不是太大问题,我们可以通过添加随机数来保证每次请求的URL都不相同,间接的使得缓存失效:

self.addEventListener('install', event => { event.waitUntil( caches.open(`static-${version}`) .then(cache => Promise.all( [ '/styles.css', '/script.js' ].map(url => { // cache-bust using a random query string return fetch(`${url}?${Math.random()}`).then(response => { // fail on 404, 500 etc if (!response.ok) throw Error('Not ok'); return cache.put(url, response); }) }) )) );});

上面的代码使用的是随机数作为文件版本,你当然可以使用更精确的方式,例如根据文件内容生成md5值来作为版本信息,而这个思维模式就是模块sw-precache模块的背后哲学。

sw-precache

想象一下现在我们需要实施上述绕过http缓存的解决方案。首先我们需要知道究竟站点中有多少静态资源,然后设定版本号的生成规则,接着根据静态资源再具体的编写我们的SW脚本。

不难看出,上面描述的过程可以是机械化自动化的,包括识别静态资源,生成SW脚本等。而类库sw-precache则可以帮我们完成这些工作。尤其是在构建阶段配合Gulp或者Grunt使用,具体用法我们可以摘录它官网的一段DEMO:

gulp.task('generate-service-worker', function(callback) { var swPrecache = require('sw-precache'); var rootDir = 'app'; swPrecache.write(`${rootDir}/service-worker.js`, { staticFileGlobs: [rootDir + '/**/*.{js,html,css,png,jpg,gif,svg,eot,ttf,woff}'], stripPrefix: rootDir }, callback);});

这段脚本注册了一个名为generate-service-worker的任务,用于在根目录生成一个名为service-worker.js的sw脚本,而这个脚本缓存的资源呢,则是目录下的所有脚本、样式、图片、字体等几乎所有的静态文件。

浏览器的整体缓存机制

除了HTTP标准缓存以外,浏览器还有可能存在标准以外的缓存机制。对于Chrome浏览器而言还存在Memory Cache、Push “Cache”。一个请求在查找资源的过程中经过的缓存顺序是Memory Cache、Service Worker、HTTP Cache、Push “Cache”。HTTP Cache和Service Worker已经介绍过了,接下来简单介绍Memory Cache和Push Cache

Memory Cache

“内存缓存”中主要包含的是当前文档中页面中已经抓取到的资源。例如页面上已经下载的样式、脚本、图片等。我们不排除页面可能会对这些资源再次发出请求,所以这些资源都暂存在内存中,当用户结束浏览网页并且关闭网页时,内存缓存的资源会被释放掉。

这其中最重要的缓存资源其实是preloader相关指令(例如)下载的资源。总所周知preloader的相关指令已经是页面优化的常见手段之一,而通过这些指令下载的资源也都会暂存到内存中。根据一些材料,如果资源已经存在于缓存中,则可能不会再进行preload。

需要注意的事情是,内存缓存在缓存资源时并不关心返回资源的HTTP缓存头Cache-Control是什么值,同时资源的匹配也并非仅仅是对URL做匹配,还可能会对Content-Type,CORS等其他特征做校验

Push “Cache”

“推送缓存”是针对HTTP/2标准下的推送资源设定的。推送缓存是session级别的,如果用户的session结束则资源被释放;即使URL相同但处于不同的session中也不会发生匹配。推送缓存的存储时间较短,在Chromium浏览器中只有5分钟左右,同时它也并非严格执行HTTP头中的缓存指令

Push “Cache”的优缺点

关于推送缓存,主要有以下几大特点:

  • 几乎所有的资源都能被推送,并且能够被缓存。测试过程是作者在推送资源之后尝试用fetch()、XMLHttpRequest、、
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值