深入了解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/zh-tw/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

發表回復

登錄後才能評論