新視野行銷企劃

Service Worker 與快取策略設計範例

扁平化風格的網頁封面圖,主題為「Service Worker 與快取策略設計範例」,畫面包含瀏覽器介面、齒輪、資料快取圖示與開發者人物,象徵前端快取與 PWA 技術設計概念。

Service Worker 概念與用途

在現代 Web 開發中,我們經常面臨網路連線不穩或使用者離線時的挑戰。Service Worker 應運而生,提供了一種在使用者背景中執行的腳本,它不需直接與網頁互動,卻能攔截網路請求並回傳自行定義的資源。換言之,Service Worker 像是一個介於網頁與伺服器之間的代理層,讓開發者可以掌控資源的快取與提取 developer.mozilla.org 。透過這層代理,我們可以實現離線瀏覽、快速載入,以及推播通知等進階功能,為使用者打造接近原生應用的體驗。

本真案例:想像使用者在搭乘捷運時網路不佳,但您的應用已透過 Service Worker 將關鍵資源快取於本機。即使斷網,用戶仍能看到先前載入的內容,而不是空白錯誤頁。這種「離線優先」的體驗正是 Service Worker 的魅力所在。更棒的是,一旦連回網路,Service Worker 還能靈活地從遠端更新資料,確保下次開啟時內容是新的。總而言之,Service Worker 的核心用途在於提升網站在離線或弱網路環境下的可靠性與速度。

注意:出於安全考量,Service Worker 僅能在 HTTPS 網站或本機開發環境 (localhost) 上運作。瀏覽器會阻止非安全來源的 Service Worker 註冊,因為攔截網路請求的能力若被惡意腳本利用,後果不堪設想。因此,在開始實作前,請確保您已透過 HTTPS 服務您的網頁內容。

註冊與安裝 Service Worker

了解了概念後,我們來一步步實作 Service Worker。以下將介紹如何註冊 (register) Service Worker、在安裝 (install) 階段進行快取,以及在啟用 (activate) 階段管理快取。假設我們的 Service Worker 檔名為 sw.js,並放置在網站的根目錄下。

註冊 Service Worker:

在網頁的主 JavaScript 檔案中(例如 main.js),使用瀏覽器提供的 API 註冊 Service Worker。註冊時可以指定檔案路徑和作用域 (scope)。若註冊成功,瀏覽器會在背景載入並執行 Service Worker。範例如下:

註冊 Service Worker
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js') 
    .then(registration => {
      console.log('Service Worker 已註冊成功:', registration);
    })
    .catch(error => {
      console.error('Service Worker 註冊失敗:', error);
    });
}

上述程式碼先檢查瀏覽器是否支援 Service Worker,然後呼叫 register() 方法。/sw.js 是 Service Worker 檔案的路徑。成功後,可以透過 registration 物件了解 Service Worker 的狀態;如有錯誤則在控制台列出。提示:register() 可接受 { scope: '/some/path/' } 選項來變更控制範圍,但切記 Service Worker 預設只能控制與自身檔案所在目錄相同或以下層級的資源。若將 sw.js 放在子資料夾,務必設定適當的 scope,否則無法攔截根目錄的請求。

安裝階段與預快取資源:

當瀏覽器載入並執行 Service Worker 腳本後,會觸發首次的 install 事件。在這階段通常我們會預先快取應用的核心檔案(例如首頁、CSS、JavaScript、影像資源等),以便之後能離線存取。利用 caches API 可以開啟命名的快取庫,將指定資源加入快取。範例如下,在 sw.js 中監聽安裝事件:

安裝階段預快取
const CACHE_NAME = 'site-static-v1';
const urlsToCache = [
  '/',
  '/index.html',
  '/styles.css',
  '/app.js',
  '/images/logo.png'
];

self.addEventListener('install', event => {
  // 安裝時將核心資源加入快取
  event.waitUntil(
    caches.open(CACHE_NAME).then(cache => {
      return cache.addAll(urlsToCache);
    })
  );
});

在上述程式中,我們定義了一個快取名稱(site-static-v1)以及一組需要快取的資源清單。event.waitUntil() 確保在安裝事件中,直到指定的快取操作完成後才算安裝成功。如果所有資源順利快取,Service Worker 就能順利安裝並進入下一階段。本源提醒:版本號(如 v1)用於快取版本控制。當您對網站資源做了更新,應提升版本號(例如改為 v2)以讓新的 Service Worker 在安裝時建立新的快取,避免持續使用舊資源。

啟用階段與快取管理:

安裝完成後,若先前已有舊的 Service Worker 正在控制頁面,新版本的 Service Worker 會進入 等待 (waiting) 狀態。當沒有舊版本頁面正在使用時(或在調試時手動跳過等待),會觸發 activate 事件,新 Service Worker 開始控制頁面。通常我們會在此階段進行快取清理,例如刪除舊的快取資料,以釋放空間並避免過期資源繼續被使用。範例如下:

啟用階段清理快取
self.addEventListener('activate', event => {
  const cacheWhitelist = [CACHE_NAME];
  event.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.map(cacheName => {
          if (!cacheWhitelist.includes(cacheName)) {
            // 刪除非白名單裡的舊快取
            return caches.delete(cacheName);
          }
        })
      );
    })
    .then(() => self.clients.claim())
  );
});

上述程式使用 caches.keys() 取得所有存在的快取庫名稱,過濾出非當前版本 (CACHE_NAME) 的快取並刪除。最後呼叫 self.clients.claim(),使新 Service Worker 立即接管所有客戶端頁面,而不必等使用者重新載入。至此,我們的 Service Worker 已完成註冊、安裝和啟用流程。接下來,核心的工作是攔截網路請求並套用快取策略來響應。

基本快取策略設計

Service Worker 最強大的功能之一,就是能夠攔截網路請求並決定如何響應它。透過不同的快取策略,我們可以靈活地在「網路」與「快取」之間取捨,以平衡資料新鮮度與響應速度。常見的幾種策略包括:
  • Cache First(快取優先)
  • Network First(網路優先)
  • Cache Only(僅快取)
  • Network Only(僅網路)
  • Stale-While-Revalidate(陳舊先用,後更新)

每種策略都有其適用場合,以下將逐一說明其原理並提供對應的實作範例程式碼。請注意,這些程式碼片段應寫在 Service Worker 腳本 (sw.js) 中的 fetch 事件監聽器內部,藉此攔截客戶端發出的請求。

Cache First(快取優先)

developer.chrome.com Cache First(快取優先) 策略顧名思義,就是優先從快取取得資源。當收到請求時,Service Worker 先檢查該請求對應的資源是否已存在於快取中:

  • 如果快取命中:直接返回快取的資源,省去網路延遲。
  • 如果快取沒有:再向網路請求資源,成功取得後將其存入快取,以便下次使用。

這種策略確保已快取的內容能以最快速度提供,特別適合用於不常更動的資源(例如前端框架腳本、字型檔案、圖片等)。即使使用者離線,之前快取的內容仍可提供。然而,需要注意的是,快取優先會導致資源更新延遲——只要快取有資料就不會去抓新版本,除非我們實作額外的更新機制或使用不同快取版本名稱。以下為 Cache First 的基本實作:

Cache First 實作
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(cachedResponse => {
      if (cachedResponse) {
        // 於快取中找到資源,直接回傳
        return cachedResponse;
      }
      // 快取無該資源,透過網路提取
      return fetch(event.request).then(networkResponse => {
        // 將新的資源加入快取
        return caches.open('site-static-v1').then(cache => {
          cache.put(event.request, networkResponse.clone());
          return networkResponse;
        });
      });
    })
  );
});

在這段程式碼中,caches.match(event.request) 用於搜尋任何已快取的對應資源。如果找到則立即回傳快取內容;若沒有則使用 fetch 從網路抓取。取得的 networkResponse 我們透過 cache.put 存入快取 (site-static-v1 是先前定義的快取庫),並回傳給使用者。下次相同請求來臨時,就能從快取中快速供應。不難想像,Cache First 非常適合離線優先的情境:例如使用者第二次造訪應用時,大部分靜態資源早已緩存在本地,即使斷網也能正常瀏覽。

Network First(網路優先)

developer.chrome.com 相對於快取優先,「Network First(網路優先)」策略走的是線上優先路線。它先向網路請求最新的資源,以確保資料最新鮮,但同時備援一份離線快取以防網路不可用:

  • 在線狀態:嘗試透過 fetch 從網路取得資源。如果成功,將響應內容同時保存到快取,供未來離線時使用。
  • 離線或網路請求失敗:則退而求其次,從快取中尋找最後一次存有的該資源並返回。

這種策略適合即時性高的內容,例如 API 資料或頻繁更新的頁面(如動態新聞、用戶帖子)。它保證有網路時用戶總是看到最新資料,而在無網路時至少能看到最近一次的緩存內容,不至於完全無法使用。Network First 策略的實作範例如下:

Network First 實作
self.addEventListener('fetch', event => {
  event.respondWith(
    fetch(event.request).then(networkResponse => {
      // 網路請求成功的話,更新快取
      return caches.open('site-static-v1').then(cache => {
        cache.put(event.request, networkResponse.clone());
        return networkResponse;
      });
    }).catch(() => {
      // 如果網路不可用,從快取取最後的資源
      return caches.match(event.request);
    })
  );
});

在這段程式中,我們首先執行 fetch(event.request) 嘗試抓取網路資源。如果拿到回應,接著開啟快取並 cache.put 更新緩存(確保下次離線時能取到最新版本)。respondWith 會先返回這個網路回應給使用者。萬一網路請求失敗(例如離線狀態),Promise 會被拒絕而進入 .catch,此時我們呼叫 caches.match(event.request) 來從已有的快取中尋找資源作為後備。本源提示:務必確保先前有將對應資源存入快取(可能是先前的線上請求或安裝階段預快取),否則離線時 caches.match 也會拿不到內容。總的來說,Network First 提供了一種折衷:在網路順暢時用最新資料,網路不行時至少有舊資料可用。

Cache Only(僅快取)

developer.chrome.com 有些場景下,我們希望完全依賴快取來提供內容,甚至不嘗試網路請求——這就是 Cache Only(僅快取) 策略。Service Worker 收到請求時只在快取中查找資源,如有即返回,沒有也不會再去抓取網路資源。在離線應用或固定內容的情境中,Cache Only 可以確保應用只使用事先緩存的內容運作:

Cache Only 實作
self.addEventListener('fetch', event => {
  // 直接從快取查詢並回應(不發出網路請求)
  event.respondWith(caches.match(event.request));
});

這是最簡潔的實現:一行 respondWith(caches.match()) 完成響應。只有當 event.request 事先已被快取(例如在安裝階段用 cache.addAll 預載)時,使用者才能順利取得內容。否則,若快取中找不到資源,請求將回傳 undefined 而導致失敗。因此 Cache Only 一般僅適用在明確可以預期資源都已離線準備好的情況,比如一個完全離線運行的文件瀏覽器應用,或是在安裝 Service Worker 時就將所有必要資源都打包快取的單頁應用。這種策略保障了應用即使斷網也不會嘗試連線(節省流量與電量),但代價是一旦快取遺漏或過期,資源將無法取得。

Network Only(僅網路)

developer.chrome.com 與僅快取相反,Network Only(僅網路) 策略完全不使用快取,每次請求都直接訪問網路。Service Worker 在這種策略下其實形同虛設,只是單純地將請求轉發出去,不做任何攔截處理。這聽起來像是「不策略」的策略,但在某些情況非常有用:例如處理即時更新且絕對不能使用過時資料的 API 請求、或者需要確保用戶每次操作都直達服務端的功能。

Network Only 非常容易實現:在 fetch 事件中不調用 event.respondWith(或讓函式直接 return),瀏覽器就會自行走原本的網路流程;如果要明確表達,我們可以寫一個空的響應處理,如下:

Network Only 實作
self.addEventListener('fetch', event => {
  // 不攔截,直接交給瀏覽器的默認網路處理
  // (等同於 event.respondWith(fetch(event.request)))
});

上例中,我們沒有對請求做任何特殊處理,相當於所有請求都繞過 Service Worker 快取,直接去網路抓取最新資料。使用此策略時,要承擔使用者離線或伺服器無回應時無法提供內容的風險。因此,Network Only 常用在對即時性要求極高且不可離線的功能上,如信用卡付款流程、需要強一致性的數據查詢等。在一般情況下,我們較少為靜態資源使用純網路策略,但有時會為了避免干擾而讓某些特定接口不被 Service Worker 快取(比如後台管理介面的 API),這時就可以對那些路由採用 Network Only。總而言之,僅網路策略保證了每次都從源頭取得最新資料,但失去快取帶來的速度與離線優勢。

Stale-While-Revalidate(先陳舊後驗證)

developer.chrome.com Stale-While-Revalidate(陳舊先用,後更新) 策略可以說是結合了前幾種方法的優點,略具複雜但非常實用。它的理念是:先快速返回快取中的舊資源(stale),同時在背景發出網路請求以取得最新資源並更新快取(revalidate)。這樣用戶立即獲得回應的同時,我們悄悄確保下次請求時快取已是最新內容。其運作步驟如下:

  • 第一步(無快取時):資源尚未被快取,跟 Network First 類似,從網路抓取並緩存,返回最新內容。
  • 隨後的請求:發現快取中已有舊的響應,立即返回它讓使用者不中斷。然而同時(Background)向網路取新內容。
  • 取得新內容後:更新快取中該資源的快取版本。但本次請求用戶已拿到舊內容,不會等待新內容。等到下一次相同請求時,用戶將拿到更新後的資源。

這種「先用舊的頂著,背後更新新的」策略非常適合對即時性要求不那麼嚴苛但又希望最終一致的資源,例如個人頭像、文章列表等——即使不是最新的也無傷大雅,但還是希望有機會更新。下面是 Stale-While-Revalidate 的實現範例:

Stale-While-Revalidate 實作
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.open('site-static-v1').then(cache => {
      return cache.match(event.request).then(cachedResponse => {
        const fetchPromise = fetch(event.request).then(networkResponse => {
          // 獲取最新資源後更新快取
          cache.put(event.request, networkResponse.clone());
          return networkResponse;
        });
        // 快取有則立即回應,沒有則等待網路
        return cachedResponse || fetchPromise;
      });
    })
  );
});

以上程式碼中,我們在收到請求時打開特定的快取,先用 cache.match 檢查是否有舊響應。然後不管有無,我們都啟動一個 fetchPromise 去網路抓取新資源。接著 respondWith 的重點是回傳 cachedResponse || fetchPromise:也就是優先返回快取內容(若存在),同時瀏覽器仍在背景執行 fetchPromise。如果快取沒有舊內容,那就直接等網路回應。等網路拿到後,我們使用 cache.put 更新快取。如此一來,用戶在有舊內容時能秒開頁面,而更新的資源悄悄存好,下次就能即時提供最新版本。Stale-While-Revalidate 策略在實務中極為常見,因為它在用戶體驗和資料新鮮度間取得了絕妙的平衡:用戶幾乎無感延遲,又能確保長期使用下內容不會一成不變。

Service Worker 部署與測試

完成 Service Worker 的編寫後,最後一哩路是將它部署到正確的環境並進行測試與調試。由於 Service Worker 涉及瀏覽器背景執行與快取行為,我們需要特別注意以下事項,以確保部署順利且功能如預期:

  • 本機開發與 HTTPS:正如前面提及,Service Worker 要求網站透過 HTTPS 提供。在本機開發時,可以使用 localhost(被視為安全來源)進行測試。如果您只是開啟檔案(file://)模式,Service Worker 將無法註冊。建議使用簡易的本地開發伺服器,例如 Node.js 的 serve 套件或 Python 簡易HTTP伺服器 (python -m http.server),將專案架站在 http://localhost:PORT 下測試。確認瀏覽器 Console 中無報錯訊息,且 navigator.serviceWorker.controller 狀態正常。
  • 首次載入與快取填充:部署後,用線上狀態載入網頁,讓 Service Worker 完成安裝並快取必要資源。您可以在瀏覽器的開發者工具中,透過 Application (或 應用程式) 面板的 Service Workers 頁籤查看註冊情況。正常的話,應能看到新註冊的 Service Worker 處於 Active 或 Activated 狀態。此時建議嘗試關閉網路或切換到離線模式,然後重新載入網頁,確認快取策略是否發揮作用——離線時原本應快取的內容是否順利顯示,是否有資源取自快取而非網路。
  • Chrome DevTools 調試:Chrome 等瀏覽器提供了豐富的工具來調試 Service Worker。在 Application 面板 > Service Workers 頁面,您可以:
    • 勾選 "Offline" 或在 Network 面板將網路狀態設為 Offline,以模擬無網環境下的行為。
    • 勾選 "Update on reload",讓瀏覽器每次載入頁面都自動尋找並套用更新的 Service Worker(方便開發時測試更新機制)。
    • 查看 Service Worker 列表中的版本狀態:如 installing、waiting、active 等。如果有新的 Service Worker 在 waiting,可按 Skip Waiting 讓其立即接管。
    • 在 Cache Storage 區域檢視快取內容。您可以展開特定的 Cache 名稱(例如我們定義的 site-static-v1),檢查裡面列出的資源清單,確認是否與預期相符。
    • 使用 Console 日誌來除錯:在 Service Worker 腳本中加上 console.log 語句,透過 Application > Service Workers 選單中的 Inspect 或 檢視 按鈕打開 Service Worker 的專屬除錯視窗,能看到那些 console 輸出。此外也可以在 Sources 面板中找到 sw.js 並下斷點進行偵錯。
  • 部署更新與版本控制:當您對 Service Worker 或快取資源做了修改,部署新版時要注意舊的快取可能造成的影響。由於瀏覽器對已安裝的 Service Worker 採用惰性更新(通常每隔24小時或使用者重載時檢查),若新版本的 sw.js 檔案內容不變,瀏覽器可能不會重新載入它。因此務必在發佈更新時修改 Service Worker 檔案的某處(哪怕只是版本號註解),以確保瀏覽器察覺變化並進行更新流程。新 Service Worker 安裝後,由於預設採「等待中」策略,舊版仍掌控當前頁面,導致新的快取內容可能未被使用。您可以提示用戶關閉所有頁籤或透過程式主動調用 self.skipWaiting() 和 clients.claim() 來加速新舊交替。快取部分,正如前述,我們通常使用版本化的 CACHE_NAME 並在 activate 階段刪除陳舊快取,以避免新版網站仍讀取到舊版快取的資源。

總而言之,部署與測試階段要仔細驗證 Service Worker 的生命週期(安裝->等待->啟用)是否正常循環,快取策略是否按預期執行,以及在各種網路條件下(線上、離線、慢速)應用都能提供良好的用戶體驗。多善用瀏覽器提供的開發者工具,可以讓您對 Service Worker 的運作狀況了若指掌。

常見問答(FAQ)

Q1: 為什麼已更新網站內容但使用者仍看到舊版(快取更新失效)?
A: 這通常與 Service Worker 的快取策略和更新機制有關。首先,檢查您是否有更新 Service Worker 檔案本身——因為瀏覽器只有在發現新的 Service Worker 檔案內容(或版本)時才會啟動更新流程。如果 sw.js 沒變,瀏覽器可能不會重新下載,自然也不會更新快取。解決方式是每次部署新版本時修改 Service Worker 檔(哪怕加個註解)以確保更新被偵測。另外,即便 Service Worker 更新了,舊的 Service Worker 可能仍在控制現有頁面(處於 activated 狀態),新的 Service Worker 需等到使用者關閉頁面或您手動 skip waiting 後才接管。在此期間,用戶還是會繼續使用舊的快取內容。建議在新的 Service Worker activate 階段使用版本化的 CACHE_NAME 並刪除舊快取,確保新版本能使用新資源。同時可以透過主應用程式監聽 registration.updatefound 等事件,在有新版本時提示使用者重新整理。一句話:更新不顯示通常是因為快取還沒換新,您需要確保 Service Worker 及 Cache 都按照新版本正確切換。
Q2: Service Worker 的作用域 (scope) 常見陷阱有哪些?
A: 最大的陷阱是不瞭解 Service Worker 檔案位置決定了預設作用域。例如,如果您的網站結構是將 sw.js 放在 /js/ 子資料夾下且沒有特別指定 scope,那麼此 Service Worker 只能攔截 /js/ 路徑下的請求,對網站其他部分無能為力。很多開發者初次嘗試時,將 Service Worker 檔案放在子路徑,結果發現 fetch 事件沒有觸發,就是因為請求路徑不在作用域內。解決辦法有兩種:(1) 將 sw.js 挪到根目錄,使其預設作用域涵蓋整個網站;(2) 在 navigator.serviceWorker.register() 時傳入 { scope: '/' } 選項,明確設定作用域為全站(此做法需要確保響應頭允許更廣的作用域,否則可能被拒絕)。另一個相關陷阱是末尾斜線的問題:若指定 scope 為 /app 沒有斜線,可能瀏覽器會取預設的 scope /app/(自動加斜線)導致認知偏差。一般建議顯式地以斜線結尾,如 { scope: '/app/' }。總之,務必確認 Service Worker 的作用域涵蓋了您想控制的路徑,否則它將聽不到那些路徑的請求。
Q3: Service Worker 能攔截哪些類型的請求?只限於檔案或也包括 API 請求?
A: Service Worker 可以攔截幾乎所有類型的網路請求,只要請求的 URL 位於它的作用域之內。這意味著不論是 HTML 頁面、CSS/JS 檔案、影像,還是透過 Fetch/XHR 發出的 API 資料請求,只要路徑符合 Service Worker 控制範圍,都會觸發 fetch 事件進而被攔截處理 gist.github.com 。因此您可以在 Service Worker 中對 API 請求套用快取策略,甚至對第三方資源(如 CDN 圖片)進行代理。不過,需要留意跨網域的請求:默認情況下,Service Worker 無法改變請求的網域,它只能攔截相同來源 (same origin) 或受 CORS 授權的資源。如果您的網頁透過 CDN 或跨網域抓取資料,仍然可以被 Service Worker 攔截,但必須確保響應允許被快取(例如適當的 CORS header)。另外,Service Worker 無法攔截像 <iframe> 或 <img src="data:..."> 這種不經網路的直嵌資源,因為沒有 HTTP 流程。大體上,Service Worker 就像全站的請求管理員,對受控範圍內的 HTTP(S) 請求都能施展身手。
Q4: 開發過程中發現 Service Worker 總是緩存過期的資源,怎麼避免用戶拿到陳舊資料?
A: 這涉及快取失效策略的設計。在開發過程中,您可以透過 DevTools 的 Disable Cache 或 Update on reload 等選項避免快取影響,但在實際部署時,需要有機制確保快取不會無限期提供舊資料。以下是幾個建議:

採用 Stale-While-Revalidate:如前所述,它能在背景更新快取,確保用戶多次訪問間隔期間快取能獲得刷新。

快取版本與過期:對於 Cache First 策略,請務必隨版本變更快取名稱,讓新的 Service Worker 安裝時自動棄用舊快取。此外,您也可以在 Fetch 處理時加上資源的版本查詢參數(例如 file.js?v=123),一旦版本變動就視為不同資源以重新抓取。

使用 Cache-Control/ETag 機制:雖然 Service Worker 可以完全接管快取,但您仍可結合伺服器的 HTTP 標頭來判斷資源是否更新。例如,在 Network First 策略中,即便網路可用,也可以先 fetch 後檢查 response.headers 的 Last-Modified 或 ETag,決定是否要替換本地快取。

主動推送更新通知:進階一點,可以利用 Service Worker 的推播通知或主動同步 (background sync) 來告知用戶有新版本,讓他們同意或自動刷新。

最重要的是制定符合應用需求的快取期限。例如快速變動的 API 資料可選擇 Network First 或極短暫的快取,穩定的靜態資源則可 Cache First 並長時間快取。透過策略組合,達到既有速度又有新鮮度的平衡。
Q5: 我可以一次使用多個快取策略嗎?
A: 當然可以!實際的 PWA 應用中,不同類型的資源通常搭配不同策略。例如:HTML 頁面可使用 Network First 確保內容最新但提供離線後援,CSS/JS 檔案使用 Cache First 確保快速載入,圖片可能用 Stale-While-Revalidate 取得最佳效能與更新平衡,而某些API 請求則乾脆 Network Only 保證即時性。您可以在 Service Worker 的 fetch 事件中根據 event.request 的類型或 URL 路徑來選擇策略。舉例來說:
多策略組合範例
self.addEventListener('fetch', event => {
  const req = event.request;
  const url = new URL(req.url);

  if (req.mode === 'navigate') {
    // 網頁導航請求 (HTML) -> 網路優先
    event.respondWith(/* network-first handler */);
  } else if (url.pathname.startsWith('/api/')) {
    // API 請求 -> 網路優先或僅網路
    event.respondWith(/* network-only or network-first handler */);
  } else if (req.destination === 'image') {
    // 圖片資源 -> 快取優先或陳舊後更新
    event.respondWith(/* cache-first or stale-while-revalidate handler */);
  } else {
    // 其他靜態資源(CSS/JS) -> 快取優先
    event.respondWith(/* cache-first handler */);
  }
});

如上,根據請求類型選用不同策略,可以兼顧各類資源的特性,提升整體效能與使用者體驗。實務上也可以使用像 Workbox 這類的高階函式庫更方便地定義多種路由規則與策略。不論如何,靈活運用多種快取策略是 PWA 優化的關鍵,也是 Service Worker 作為網路請求「織心者」的重要價值所在。

透過本指南,我們從零開始逐步建置了一個 Service Worker,並深入講解了常用的快取策略設計範例。在真實開發中,請根據您應用的需求選擇合適的策略或它們的組合,並持續關注 Service Worker 新功能與瀏覽器支援情況。只要熟練掌握這項技術,您就能讓 Web 應用在離線狀態下依然熠熠生輝,為使用者帶來前所未有的順暢體驗。Happy coding!

CONTACT US

網站設計報價洽詢

請填寫您的資料,我們將儘快與您聯繫! 為必填