深入了解ServiceWorker缓存

一、ServiceWorker缓存文件

ServiceWorker是一种可以在浏览器后台运行JavaScript脚本的API,它能够拦截网络请求并且将其转化为来自缓存的响应。这意味着ServiceWorker能够将资源缓存到本地,甚至可以使你的web应用离线使用!下面是一个简单的示例:


// 注册ServiceWorker
if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/serviceworker.js').then(function(registration) {
      console.log('ServiceWorker registration successful with scope: ', registration.scope);
    }, function(err) {
      console.log('ServiceWorker registration failed: ', err);
    });
  });
}

// 缓存文件
self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open('my-cache').then(function(cache) {
      return cache.addAll([
        '/',
        '/index.html',
        '/styles.css',
        '/script.js',
        '/logo.png'
      ]);
    })
  );
});

// 返回缓存的响应
self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request).then(function(response) {
      return response || fetch(event.request);
    })
  );
});

这段代码向我们说明ServiceWorker如何缓存文件。在ServiceWorker注册之后,它会通过install事件进行缓存。缓存文件的代码片段如下:


self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open('my-cache').then(function(cache) {
      return cache.addAll([
        '/',
        '/index.html',
        '/styles.css',
        '/script.js',
        '/logo.png'
      ]);
    })
  );
});

我们首先打开一个名为’my-cache’的缓存。然后通过cache.addAll()方法将我们需要缓存的文件添加到缓存中。在事件的最后,我们需要调用event.waitUntil()以确保ServiceWorker在缓存过程中不会被中止。

如果我们尝试缓存已经存在的文件,如/,它将被忽略并不会影响后续步骤。一旦文件被成功缓存,我们可以在浏览器的开发工具中查看缓存的文件,如下图所示:

二、ServiceWorker缓存大小

ServiceWorker缓存大小与其他类型的缓存一样,是有限制的,不同浏览器之间也有所不同。

在Chrome中,ServiceWorker缓存的大小默认为50MB。在Firefox中,这个值默认为50MB,但是可以通过about:config进行更改。在Safari中,ServiceWorker缓存的大小默认为0,但是可以通过开启web开发者模式进行更改。

当缓存大小达到最大限制时,ServiceWorker将无法缓存新的文件并且会删除过期的文件以腾出空间。如果你使用缓存Api(caches.open()、cache.addAll()、cache.put()等),你可以通过cache.keys()方法查看缓存中的所有的键名并且去删除过期的文件。


// 清空过期的文件
self.addEventListener('activate', function(event) {
  var cacheKeeplist = ['my-cache'];
  
  event.waitUntil(
    caches.keys().then(function(keyList) {
      return Promise.all(keyList.map(function(key) {
        if (cacheKeeplist.indexOf(key) === -1) {
          return caches.delete(key);
        }
      }));
    })
  );
});

上面的代码展示了如何清空过期的文件。它通过event.waitUntil()方法来等待Promise的返回结果,以保证ServiceWorker不会在删除过期文件时被中止。同时,我们只删除名为’my-cache’的缓存,其他缓存不受影响。

三、ServiceWorker缓存文件版本控制

对于每次缓存文件的更新,为了防止浏览器缓存旧的文件,你需要对ServiceWorker进行版本控制。这可以通过在ServiceWorker文件中添加一个字符串版本号来实现。

下面是一个示例:


// 版本号
var CACHE_NAME = 'my-cache-v1';

// 注册ServiceWorker
if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/serviceworker.js').then(function(registration) {
      console.log('ServiceWorker registration successful with scope: ', registration.scope);
    }, function(err) {
      console.log('ServiceWorker registration failed: ', err);
    });
  });
}

// 缓存文件
self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open(CACHE_NAME).then(function(cache) {
      return cache.addAll([
        '/',
        '/index.html',
        '/styles.css',
        '/script.js',
        '/logo.png'
      ]);
    })
  );
});

// 返回缓存的响应
self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request).then(function(response) {
      return response || fetch(event.request);
    })
  );
});

// 更新缓存
self.addEventListener('activate', function(event) {
  var cacheKeeplist = [CACHE_NAME];
  
  event.waitUntil(
    caches.keys().then(function(keyList) {
      return Promise.all(keyList.map(function(key) {
        if (cacheKeeplist.indexOf(key) === -1) {
          return caches.delete(key);
        }
      }));
    })
  );
});

我们在这个例子中添加了一个版本号——’my-cache-v1’,以避免缓存的文件与以前的版本相混淆。另外,在更新缓存时,应在缓存版本中更新版本号。

在实际开发过程中,当你进行任何修改时,都应该更改版本号。任何版本不同的ServiceWorker都将触发activate事件,以便删除旧缓存并更新到新缓存中。

在实际项目中,版本控制通常会涉及自动构建和更新版本号,以避免手动操作。

四、ServiceWorker缓存策略

缓存策略是指ServiceWorker决定返回哪个响应的算法。通常,它根据请求的URL及请求方式(GET、POST、PUT等)进行决策。

常见的缓存策略有:

  • networkFirst(网络优先):ServiceWorker优先检查网络是否可用,如果网络正常,则从网络中获取响应,如果网络不可用,则从缓存中获取响应。
  • cacheFirst(缓存优先):ServiceWorker优先检查缓存是否存在请求的资源,如果存在,则从缓存中获取响应,否则从网络中获取响应。
  • cacheOnly(仅缓存):ServiceWorker只从缓存中获取资源,如果没有缓存,则返回错误响应。
  • networkOnly(仅网络):ServiceWorker只从网络中获取资源,如果没有网络,则返回错误响应。
  • staleWhileRevalidate(过期更新):ServiceWorker优先从缓存中获取响应,并将其返回给浏览器,然后在后台发送请求以获取最新版本的响应,并更新缓存以供下次使用。

// 网络优先
self.addEventListener('fetch', function(event) {
  event.respondWith(
    fetch(event.request).catch(function() {
      return caches.match(event.request);
    })
  );
});

// 缓存优先
self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request).then(function(response) {
      return response || fetch(event.request);
    })
  );
});

// 仅缓存
self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
  );
});

// 仅网络
self.addEventListener('fetch', function(event) {
  event.respondWith(
    fetch(event.request)
  );
});

// 过期更新
self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.open('my-cache').then(function(cache) {
      return cache.match(event.request).then(function(response) {
        var fetchPromise = fetch(event.request).then(function(networkResponse) {
          cache.put(event.request, networkResponse.clone());
          return networkResponse;
        });
        return response || fetchPromise;
      });
    })
  );
});

上面的代码展示了各种缓存策略的示例。你可以选择一个适合你的需求的缓存策略来使用。

结论

通过ServiceWorker缓存机制,你可以轻松地将资源缓存到本地,使得你的Web应用可以离线使用。在不同浏览器中,ServiceWorker大小,版本控制方式和缓存策略会有所不同,因此你需要针对不同的浏览器进行优化。缓存策略应根据你的网站的需求进行选择,以实现最佳的性能和用户体验。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/309718.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2025-01-04 19:31
下一篇 2025-01-04 19:31

相关推荐

  • Python 数据缓存及其应用

    本文将为大家详细介绍Python数据缓存,并提供相关代码示例。 一、Python 数据缓存基础概念 Python 是一种解释型语言,每次执行完一条语句后就会将内存中的结果清空,如果…

    编程 2025-04-29
  • Python缓存图片的处理方式

    本文将从多个方面详细阐述Python缓存图片的处理方式,包括缓存原理、缓存框架、缓存策略、缓存更新和缓存清除等方面。 一、缓存原理 缓存是一种提高应用程序性能的技术,在网络应用中流…

    编程 2025-04-29
  • Java图片缓存的实现与优化

    Java中的图片缓存是Web开发中常用的技术,它可以提高网页的加载速度和用户体验。本文将从以下三个方面对Java图片缓存进行详细阐述: 一、图片缓存的基本实现 图片缓存技术是指将一…

    编程 2025-04-27
  • 深入解析Vue3 defineExpose

    Vue 3在开发过程中引入了新的API `defineExpose`。在以前的版本中,我们经常使用 `$attrs` 和` $listeners` 实现父组件与子组件之间的通信,但…

    编程 2025-04-25
  • 深入理解byte转int

    一、字节与比特 在讨论byte转int之前,我们需要了解字节和比特的概念。字节是计算机存储单位的一种,通常表示8个比特(bit),即1字节=8比特。比特是计算机中最小的数据单位,是…

    编程 2025-04-25
  • 深入理解Flutter StreamBuilder

    一、什么是Flutter StreamBuilder? Flutter StreamBuilder是Flutter框架中的一个内置小部件,它可以监测数据流(Stream)中数据的变…

    编程 2025-04-25
  • 深入探讨OpenCV版本

    OpenCV是一个用于计算机视觉应用程序的开源库。它是由英特尔公司创建的,现已由Willow Garage管理。OpenCV旨在提供一个易于使用的计算机视觉和机器学习基础架构,以实…

    编程 2025-04-25
  • 深入了解scala-maven-plugin

    一、简介 Scala-maven-plugin 是一个创造和管理 Scala 项目的maven插件,它可以自动生成基本项目结构、依赖配置、Scala文件等。使用它可以使我们专注于代…

    编程 2025-04-25
  • Hibernate缓存详解

    在关系型数据库中,为了减少重复查询并提高查询效率,采用缓存技术是非常常见的做法。Hibernate缓存是Hibernate框架为了加速读取数据而提供的一种机制。通过缓存,Hiber…

    编程 2025-04-25
  • 深入了解LaTeX的脚注(latexfootnote)

    一、基本介绍 LaTeX作为一种排版软件,具有各种各样的功能,其中脚注(footnote)是一个十分重要的功能之一。在LaTeX中,脚注是用命令latexfootnote来实现的。…

    编程 2025-04-25

发表回复

登录后才能评论