专栏首页IMWeb前端团队PWA之离线缓存(一)

PWA之离线缓存(一)

本文作者:IMWeb json 原文出处:IMWeb社区 未经同意,禁止转载

PWA是什么

PWA全称是Progressive Web Apps, 是一种渐进式增强 WEB 应用。 这里的渐进式增强是指无论用户用的是什么浏览器都能保证应用能正常工作。

PWA特性:

  • 渐进增强 : 能够让每一位用户使用,无论用户使用什么浏览器,因为它是始终以渐进增强为原则
  • 可安装 : 可以像原生APP在主屏幕上留有图标。
  • 离线缓存 :通过Service Worker使得 Web App 也可以做到像 Native App 那样可以离线使用、消息推送的功能。
  • 安全性 : 通过 HTTPS 来提供服务来防止网络窥探,保证内容不被篡改。

PWA是应用一系列技术组成的集合, 其核心技术包括 App Manifest、Service Worker、Web Push等等。

Service Worker详解

service worker是什么?

service worker是独立于当前页面的运行在浏览器后台进程的脚本。利用它,我们可以拦截页面请求,缓存文件。 使用service worker有几点注意:

  • 页面必须基于https
  • 独立于当前网页进程,不会对主线程造成影响
  • 不能操作DOM,但可以通过postMessage与页面通信
  • 可以拦截作用域范围内的所有请求

浏览器支持情况

可以看出大部分现代浏览器都已经得到了支持。

生命周期

从图中可以看出,用户访问某个URL的时候, 服务器返回相应的资源文件,此时会调用navigator.serviceWorker.register('/teacher/sw.js') , 下载sw.js 。 执行sw。如果出现错误。serviceWorker会被废弃掉。 当执行完sw文件后,出触发install事件, 此时可以调用cache API去缓存想要的静态资源 。 注意, 如果缓存失败, serviceWorker也将装载失败 。 待serviceWorker装载完成后, 触发activate事件。serviceWorker准备就绪。 此时可以监听fetch事件拦截浏览器请求了。

demo

 <html>
    <head>
        <title>pwa test</title>
    </head>
    <body>
        hello world;
        <script>
          if ('serviceWorker' in navigator) {             
            navigator.serviceWorker.register('/teacher/sw.js').then(function (registration) {

              console.log('ServiceWorker registration successful with scope: ', registration.scope);
            }).catch(function (err) {                     
              // 注册失败 :(
              console.log('ServiceWorker registration failed: ', err);
            });
          }
          setTimeout(() => {
            const img = new Image();
            img.src = "/teacher/1@2x_d3458ef8fd9ebd0f7fe4ab1f886b572f.gif";
            document.body.appendChild(img);
          }, 3000);
        </script>
    </body>
</html>

如图html文件中,可以在文件末尾插入如上代码来注册service worker。

  • sw 是挂载到navigator对象上的, 使用之前先判断是否存在
  • 作用域:SW 的默认作用域为基于当前文件 URL 的 ./, 如果想要改变作用域,可以使用scope eg:
 navigator.serviceWorker.register('/teacher/sw.js', {scope: '../..'})

sw.js文件如下:

self.addEventListener('install', (event) => {
  console.log('V1 installing…11', event);

  event.waitUntil(
    caches.open("static-v1").then(cache => cache.add("https://7.url.cn/fudao/pc/bd3fa67732209940a5ca1db12970e41e.png"))
  );
});

self.addEventListener('activate', (event) => {
  console.log('V1 now ready to handle fetches!12');
});

self.addEventListener("fetch", event => {
  const url = new URL(event.request.url);
  console.log(33333, event.request);
});

监听install事件, 缓存资源文件。 如果都缓存成功,那么OK,service worker安装成功。 这里缓存资源时, 定义了一个缓存名字static-v1 , 打开这个缓存,将图片文件添加进去。

离线资源更新

1、如果业务的静态资源更新了, 需要修改sw.js文件,一个B的修改都会引起浏览器的重新下载sw文件, 然后触发install , 装载新的离线资源。 但要注意,新的service worker不会立即activate , 因为老的service worker还在, 新的sw处于waiting状态。

必须关闭当前sw控制的所有页面,然后再访问当前页面才能使新的sw激活。 比较麻烦。 解决办法是 使用 self.skipWaiting();来跳过等待,直接使用新的sw激活。

self.addEventListener('install', (event) => {
  self.skipWaiting();
  console.log('V1 installing…11', event);

2、如果更改sw, 什么时候会触发新的sw的下载呢, 答案是刷新页面的时候 。 我们做资源缓存, 发布文件后不能要求用户一定刷新页面, 如果停留在一个页面较长时间, 但仍然想使用新的缓存资源,该怎么做呢? 可以在注册的时候调用update()方法

navigator.serviceWorker.register('/teacher/sw.js').then(function (registration) {
     setInterval(function() {
         console.log('setInterval');
         registration.update();
     }, 4000);
     // 注册成功
     console.log('ServiceWorker registration successful with scope: ', registration.scope);
 }).catch(function (err) {                     
     // 注册失败 :(
     console.log('ServiceWorker registration failed: ', err);
 });

每隔固定的4s, 实际使用中可以更长时间, 去下载一次sw, 结合skipWaiting , 可以实现体验更好的缓存资源的更新 。

待续

关于缓存策略、上报方案等实践,敬请期待。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 浏览器缓存

    原文链接:http://www.cun-xu.cn/index.php/2018/12/26/浏览器缓存/

    IMWeb前端团队
  • 缓存策略

    对于浏览器端的缓存来讲,这些规则是在HTTP协议头和HTML页面的Meta标签中定义的。他们分别从新鲜度和校验值两个维度来规定浏览器是否可以直接使用缓存中的副本...

    IMWeb前端团队
  • 缓存策略

    本文作者:IMWeb daihuimi 原文出处:IMWeb社区 未经同意,禁止转载 学习整理了web缓存的一些策略,如有不正确的地方,欢迎指正。 ?...

    IMWeb前端团队
  • windows系统构建golang+opencv环境

    python+opencv已经比较成熟了,但是比起go,python太缺乏秩序,所以打算后面用go玩opencv。

    大福加冰
  • 2017机器学习与自然语言处理学术全景图:多产的作者与机构都是谁?

    机器之心
  • 性能测试监控平台:influxdb+grafana+jmeter

    原来的文章介绍了InfluxDB、Telegraf、Grafana的安装和使用方法,这篇文章,介绍下如何利用这些开源工具搭建性能测试监控平台。。。

    写博客的老张
  • Build 2016:细数给开发者的福利 | TW洞见

    今日洞见 文章作者/配图来自ThoughtWorks:陈计节。 本文所有内容,包括文字、图片和音视频资料,版权均属ThoughtWorks公司所有,任何媒体、网...

    ThoughtWorks
  • 性能测试-Jmeter服务器性能监控

    最近很火的“病毒”,搞得人心惶惶。大家记得戴口罩啊。新的一年:祝大家事事顺心,阖家欢乐,心想事成!

    用户6367961
  • K8S 生态周报| 2019-07-08~2019-07-14

    「K8S 生态周报」内容主要包含我所接触到的 K8S 生态相关的每周值得推荐的一些信息。欢迎订阅知乎专栏「k8s生态」。本周为什么发布时间比往常迟呢?因为上周我...

    Jintao Zhang
  • Sqoop导入数据之提供密码别名

        最近遇到sqoop密码导入的问题,记录下。Sqoop从关系型数据库导入到hdfs中时,需要关系型数据库的密码,但是密码明文展示不安全,所以在hadoop...

    克虏伯

扫码关注云+社区

领取腾讯云代金券