漸進式網頁應用程式:離線

1. 歡迎

在本實驗室中,您將使用現有的網頁應用程式,並讓該應用程式離線運作。這是漸進式網頁應用程式研討會的一系列隨附程式碼研究室中的第一個。本系列還有七個程式碼研究室。

課程內容

  • 手動撰寫 Service Worker
  • 在現有網頁應用程式中新增 Service Worker
  • 使用 Service Worker 和 Cache Storage API,讓資源可離線存取

注意事項

  • 基本 HTML 和 JavaScript

軟硬體需求

2. 開始設定

首先,請複製或下載完成本程式碼研究室所需的範例程式碼:

如果複製存放區,請確認您位於 starter 分支版本中。ZIP 檔案也包含該分支版本的程式碼。

這個程式碼集需要 Node.js 14 以上版本。取得程式碼後,請在程式碼資料夾中從指令列執行 npm ci,安裝所有需要的依附元件。接著執行 npm start,啟動本程式碼研究室的開發伺服器。

原始碼的 README.md 檔案會說明所有發布的檔案。此外,您在本程式碼研究室中會使用下列主要現有檔案:

金鑰檔案

  • js/main.js - 主要應用程式 JavaScript 檔案
  • service-worker.js - 應用程式的 Service Worker 檔案

3. 測試離線

進行任何變更前,請先測試,證明網頁應用程式目前無法離線運作。如要這麼做,請讓電腦離線並重新載入網頁應用程式,或使用 Chrome 執行下列步驟:

  1. 開啟 Chrome 開發人員工具
  2. 切換至「應用程式」分頁
  3. 切換至「Service Workers」部分
  4. 勾選「離線」核取方塊
  5. 在不關閉 Chrome 開發人員工具的情況下重新整理頁面

Chrome 開發人員工具的「應用程式」分頁已開啟「Service Worker」,且已勾選「離線」核取方塊

測試網站後,如果網站無法離線載入,就可以開始新增一些線上功能!取消勾選離線核取方塊,然後繼續下一個步驟。

4. 在其他平台延續互動

現在可以新增基本服務工作人員了!這項作業會分兩個步驟進行:註冊 Service Worker 和快取資源。

註冊 Service Worker

目前已有空白的 Service Worker 檔案,因此為了確保變更會顯示出來,請在應用程式中註冊該檔案。如要這麼做,請在 js/main.js 頂端新增下列程式碼:

// Register the service worker
if ('serviceWorker' in navigator) {
  // Wait for the 'load' event to not block other work
  window.addEventListener('load', async () => {
    // Try to register the service worker.
    try {
      // Capture the registration for later use, if needed
      let reg;

      // Use ES Module version of our Service Worker in development
      if (import.meta.env?.DEV) {
        reg = await navigator.serviceWorker.register('/service-worker.js', {
          type: 'module',
        });
      } else {
        // In production, use the normal service worker registration
        reg = await navigator.serviceWorker.register('/service-worker.js');
      }

      console.log('Service worker registered! 😎', reg);
    } catch (err) {
      console.log('😥 Service worker registration failed: ', err);
    }
  });
}

說明

網頁載入後,這段程式碼會註冊空白的 service-worker.js Service Worker 檔案,前提是網站支援 Service Worker。

預先快取資源

如要讓網頁應用程式離線運作,瀏覽器必須能夠回應網路要求,並選擇將要求傳送至何處。如要這樣做,請在 service-worker.js 中加入下列內容:

// Choose a cache name
const cacheName = 'cache-v1';
// List the files to precache
const precacheResources = ['/', '/index.html', '/css/style.css', '/js/main.js', '/js/app/editor.js', '/js/lib/actions.js'];

// When the service worker is installing, open the cache and add the precache resources to it
self.addEventListener('install', (event) => {
  console.log('Service worker install event!');
  event.waitUntil(caches.open(cacheName).then((cache) => cache.addAll(precacheResources)));
});

self.addEventListener('activate', (event) => {
  console.log('Service worker activate event!');
});

// When there's an incoming fetch request, try and respond with a precached resource, otherwise fall back to the network
self.addEventListener('fetch', (event) => {
  console.log('Fetch intercepted for:', event.request.url);
  event.respondWith(
    caches.match(event.request).then((cachedResponse) => {
      if (cachedResponse) {
        return cachedResponse;
      }
      return fetch(event.request);
    }),
  );
});

現在返回瀏覽器,關閉預覽分頁,然後再次開啟。您應該會看到服務工作人員中不同事件的對應 console.log

接著再次離線並重新整理網站。即使處於離線狀態,您應該也能看到網頁載入!

說明

在 Service Worker 的安裝事件期間,系統會使用 Cache Storage API 開啟具名快取。接著,系統會使用 cache.addAll 方法,將 precacheResources 中指定的檔案和路徑載入快取。這稱為「預先快取」,因為系統會在安裝期間預先快取一組檔案,而不是在需要或要求檔案時才快取。

服務工作人員控管網站後,要求的資源會像 Proxy 一樣經過服務工作人員。每個要求都會觸發擷取事件,這個服務工作人員會在快取中搜尋相符項目,如果找到相符項目,就會以快取資源回應。如果沒有相符的資源,系統會正常要求資源。

快取資源可避免網路要求,讓應用程式離線運作。現在應用程式在離線時可以傳回狀態碼 200!

5. 恭喜!

您已學會如何使用 Service Worker 和快取儲存空間 API,讓網路應用程式離線運作。

本系列下一個程式碼研究室是「使用 Workbox