Setting up service workers on Vultr title. A gradient background with a shield icon in the top right and a JavaScript logo in the bottom right corner.
贊助

在 Vultr 上設定 Service Worker

閱讀時間 6 分鐘

Service workers 允許在 Web 瀏覽器中執行可指令碼化的網路代理,使開發者能夠控制網頁如何響應網路請求、管理資源並構建健壯且高效能的 Web 應用。 在您的 Web 應用中學習使用 service workers 將幫助您構建諸如後臺資料同步、預取使用者接下來需要的資源、在一個地方而不是多個頁面處理資料以及其他激動人心的功能。

在本文中,我們將瞭解 service worker 的生命週期以及理解它們的工作原理的重要性。我們還將建立一個託管在 Vultr 上的示例 Web 應用,包括透過 Nginx 和 Let's Encrypt 實現的 HTTPS,這是讓 service worker 在使用者瀏覽器上執行所必需的。

Service worker 生命週期

Service workers 是事件驅動的 JavaScript 後臺任務,它們獨立於 Web 頁面的主執行緒執行。它們充當 Web 頁面和網路之間的中介,提供離線支援、推送通知和後臺同步等功能。

理解 service worker 的生命週期對於在 Web 專案中有效實現和管理它們至關重要。此生命週期包含三個主要階段:

  • 註冊:初始步驟是 註冊階段,在此階段我們檢查瀏覽器是否支援 service workers。
  • 安裝:註冊後,當用戶訪問網站時,service worker 會立即下載 用於 service worker 控制的 URL,併為指定的 URL 建立快取。每當網站有新版本時,就會觸發安裝,並在後臺安裝新版本。
  • 啟用:在啟用階段,service worker 會接管其作用域內的 Web 頁面,並開始攔截網路請求。此階段通常是清理舊快取並執行任何必要的初始化任務的合適階段。

在 Vultr 上設定專案目錄

首先,請遵循我們上一篇文章中“在 Vultr 上部署伺服器”部分中的步驟來部署伺服器。此專案不需要特定的 Marketplace 應用。接下來,讓我們透過 SSH 訪問伺服器終端,併為我們的 Web 應用設定一個專案。我們將建立一個帶有 CSS 樣式的著陸頁,並在我們的主 JavaScript 檔案中新增一個指令碼,用於檢查瀏覽器是否支援 service workers 並註冊 service worker。

我們將使用 Nano 文字編輯器在伺服器上建立和編輯專案檔案。您可以在 快捷鍵備忘單 中查詢使用 Nano 的幫助。

  1. 建立一個專案目錄,並進入該目錄。

    bash
    mkdir sample
    cd sample
    
  2. 建立一個 HTML 檔案。

    bash
    nano index.html
    
  3. 將以下程式碼複製並貼上到 index.html 檔案中。

    html
    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>My Service Worker App</title>
        <link rel="stylesheet" href="/main.css" />
      </head>
    
      <body>
        <h1>Welcome to My Service Worker App</h1>
    
        <p>This is a sample paragraph with <a href="#">a link</a>.</p>
    
        <script src="/app.js"></script>
      </body>
    </html>
    
  4. 儲存並退出檔案。

  5. 建立一個 CSS 檔案。

    bash
    nano main.css
    
  6. 將以下程式碼複製並貼上到 main.css 檔案中。

    css
    body,
    h1 {
      margin: 0;
      padding: 0;
    }
    
    h1 {
      text-align: center;
      margin-top: 50px;
    }
    
    p {
      text-align: center;
    }
    
    body {
      background-color: #add8e6;
      font-family: Arial, sans-serif;
    }
    
    a {
      color: #00ff7b;
    }
    
    a:hover {
      text-decoration: underline;
    }
    
  7. 儲存並關閉檔案。

建立 Service Worker

現在您已經設定了專案目錄,在本節中,您將探索 service worker 如何被註冊、安裝和啟用。

安裝和啟用 Service Worker

讓我們向專案中新增一個基本的 service worker,我們的主 JavaScript 應用可以與之互動。

  1. sample 目錄中,建立一個 JavaScript 檔案。

    bash
    nano sw.js
    
  2. 將以下程式碼複製並貼上到 sw.js 檔案中。

    js
    const CACHE_NAME = "my-cache-v1";
    const urlsToCache = ["/", "/index.html", "/main.css"];
    
    self.addEventListener("install", (event) => {
      event.waitUntil(
        caches.open(CACHE_NAME).then((cache) => {
          console.log("Opened cache");
          return cache.addAll(urlsToCache);
        }),
      );
    });
    
    self.addEventListener("activate", (event) => {
      event.waitUntil(
        caches.keys().then((cacheNames) => {
          return Promise.all(
            cacheNames
              .filter((cacheName) => {
                return cacheName !== CACHE_NAME;
              })
              .map((cacheName) => {
                return caches.delete(cacheName);
              }),
          );
        }),
      );
    });
    
    self.addEventListener("fetch", (event) => {
      event.respondWith(
        caches.match(event.request).then((response) => {
          if (response) {
            return response;
          }
          return fetch(event.request);
        }),
      );
    });
    
  3. 儲存並退出檔案。

在上面的程式碼中,我們掛鉤了前面描述的三個事件。當觸發安裝事件時,我們開啟一個快取,用於我們希望控制的 URL。我們使用啟用事件來清除可能擁有的任何舊快取。最後,我們有一個 fetch 事件,它檢查使用者請求的資源是否已快取;否則,它會從網路獲取資源並返回。

註冊 Service Worker

在本節中,您將學習如何檢查瀏覽器是否支援 service workers,新增一個事件監聽器來註冊 service worker,並在 service worker 註冊後顯示一個警告。

  1. 建立一個 JavaScript 檔案。

    bash
    nano app.js
    
  2. 將以下程式碼複製並貼上到 app.js 檔案中。

    js
    if ("serviceWorker" in navigator) {
      window.addEventListener("load", function () {
        navigator.serviceWorker
          .register("/sw.js")
          .then(function (registration) {
            alert(
              "Service Worker registration successful with scope: " +
                registration.scope,
            );
            if (registration.installing) {
              console.log("Service worker installing");
            } else if (registration.waiting) {
              console.log("Service worker installed");
            } else if (registration.active) {
              console.log("Service worker active");
            }
          })
          .catch(function (err) {
            alert("Service Worker registration failed: " + err);
          });
      });
    }
    
  3. 儲存並關閉檔案。

在上面的程式碼中,if ('serviceWorker' in navigator) 條件語句檢查瀏覽器是否支援 service workers。如果我們支援 service workers,我們可以使用 navigator.serviceWorker.register() 方法進行註冊,該方法提供位於 /sw.js 的指令碼。我們正在顯示一個列印作用域 URL 的警告,並將生命週期狀態記錄到控制檯。

在 Vultr 伺服器上提供 Web 應用

在本節中,您將學習如何建立一個 systemd 服務,該服務在系統啟動時自動啟動,並執行一個 Python HTTP 伺服器來提供 Web 應用。

  1. 退出 sample 目錄。

    bash
    cd ..
    
  2. 建立一個 Python 檔案。

    bash
    nano http_server.py
    
  3. 將以下程式碼複製並貼上到 http_server.py 檔案中。

    python
    import http.server
    import socketserver
    import os
    
    PORT = 8000
    DIRECTORY = "sample"
    
    sample_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "sample")
    
    mime_types = {
       ".html": "text/html",
       ".css": "text/css",
       ".js": "application/javascript",
    }
    class MyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
       def guess_type(self, path):
          _, ext = os.path.splitext(path)
          return mime_types.get(ext.lower(), "application/octet-stream")
    Handler = MyHTTPRequestHandler
    
    os.chdir(sample_dir)
    
    with socketserver.TCPServer(("", PORT), Handler) as httpd:
       print("Serving at port", PORT)
       httpd.serve_forever()
    
  4. 上面的程式碼在我們的 sample 目錄中啟動一個埠為 8000 的 Python HTTP 伺服器。

  5. 儲存並退出檔案。

  6. 允許執行 http_server.py 作為指令碼的許可權。

    bash
    chmod +x http_server.py
    
  7. 建立一個 service worker 服務檔案。

    bash
    sudo nano /etc/systemd/system/pythonserver.service
    
  8. 將以下內容貼上到服務檔案中。請務必將 UserGroup 值替換為您實際的值。另外,將 WorkingDirectory 替換為實際的 sample 目錄路徑,並將 ExecStart 替換為實際的 http_server.py 路徑。

    [Unit]
    Description= Daemon for Sample Demo Application
    After=network.target
    
    [Service]
    User=example_user
    Group=example_user
    WorkingDirectory= /example_user/sample
    ExecStart= /usr/bin/python3 /example_user/http_server.py
    
    [Install]
    WantedBy=multi-user.target
    
  9. 啟動服務。

    bash
    sudo systemctl start pythonserver
    
  10. 驗證服務狀態。

    bash
    sudo systemctl status pythonserver
    
  11. 輸出將如下所示。

    ● pythonserver.service - Daemon for Sample Demo Application
       Loaded: loaded (/etc/systemd/system/pythonserver.service; disabled; preset: enabled)
       Active: active (running) since Fri 2024-04-05 10:29:31 UTC; 3s ago
    Main PID: 10181 (python3)
       Tasks: 1 (limit: 1011)
       Memory: 8.6M
          CPU: 43ms
       CGroup: /system.slice/pythonserver.service
                └─10181 /usr/bin/python3 /example_user/http_server.py
    
  12. 啟用該服務,以便在系統每次啟動時自動啟動。

    bash
    sudo systemctl enable pythonserver
    

使用 HTTPS 保護 Vultr 上的 Web 應用

出於安全原因,Service workers 僅在 HTTPS 上下文中執行。這可以防止中間人攻擊,並降低透過網路攔截和篡改資料的風險。

第一步是為您的 Web 應用配置反向代理。我們可以使用 Nginx 來高效地處理請求和負載均衡。接下來,您需要從 Let's Encrypt 請求一個免費的 SSL 證書來新增 HTTPS。執行此操作的步驟在我們之前的文章“將 Nginx 配置為反向代理伺服器並使用 Certbot 安裝 SSL 證書”中有描述。

應用 HTTPS 後,請訪問您的應用程式 URL,如果一切正常,您將看到一個帶有 service worker 作用域的警告。您還可以檢查瀏覽器的開發者控制檯來檢視生命週期事件。第一次訪問頁面時,將開啟快取,並且 service worker 將被安裝。您可以重新整理頁面以檢視 service worker 已啟用,並且使用者可以在離線狀態下訪問網頁。要進行測試,您可以關閉網際網路連線並再次重新整理頁面。

A web page with an alert box saying "Service Worker registration successful with scope:" followed by a redacted server URL.

總結

在本文中,我們瞭解了 service workers 是什麼以及它們的生命週期的不同階段。我們還學習瞭如何建立一個具有 service worker 的 Web 應用,該應用為特定頁面和資源新增離線功能。使用 service workers 可以顯著改善使用者體驗,因為它允許使用者即使在離線狀態下也能訪問內容。

這是一篇 Vultr 的贊助文章。Vultr 是全球最大的私營雲計算平臺。Vultr 深受開發者喜愛,已為 185 個國家的 150 萬多客戶提供服務,提供靈活、可伸縮的全球雲計算、雲 GPU、裸金屬和雲端儲存解決方案。瞭解更多關於 Vultr 的資訊。