ServiceWorkerContainer: register() 方法

Baseline 已廣泛支援

此功能已成熟,可跨多種裝置和瀏覽器版本工作。它自 ⁨2018 年 4 月⁩ 起已在所有瀏覽器中可用。

安全上下文: 此功能僅在安全上下文(HTTPS)中可用,且支援此功能的瀏覽器數量有限。

注意:此功能在 Web Workers 中可用。

ServiceWorkerContainer 介面的 register() 方法用於為給定範圍建立或更新一個 ServiceWorkerRegistration。如果成功,該註冊會將提供的指令碼 URL 與一個範圍相關聯,該範圍隨後用於將文件匹配到特定的 service worker。

每個唯一的範圍只建立一個註冊。如果為已存在的範圍呼叫 register(),則該註冊將使用 scriptURL 或 options 的任何更改進行更新。如果沒有更改,則返回現有的註冊。使用相同的範圍和 scriptURL 呼叫 register() 不會重新啟動安裝過程,因此通常可以從受控頁面無條件呼叫此方法。但是,它會發送對 service worker 指令碼的網路請求,這可能會增加伺服器的負載。如果這令人擔憂,您可以使用 ServiceWorkerContainer.getRegistration() 檢查是否已存在註冊。

一個文件可能屬於具有不同 service worker 和選項的多個註冊的範圍。瀏覽器會將該文件與具有最具體範圍的匹配註冊相關聯。這確保了每個文件只執行一個 service worker。

注意: 通常最好不要定義具有重疊範圍的註冊。

語法

js
register(scriptURL)
register(scriptURL, options)

引數

scriptURL

service worker 指令碼的 URL。註冊的 service worker 檔案需要具有有效的 JavaScript MIME 型別

options 可選

包含註冊選項的物件。目前可用的選項有:

scope

一個字串,表示定義 service worker 註冊範圍的 URL;也就是說,service worker 可以控制的 URL 的範圍。

這通常被指定為相對於站點基 URL 的 URL(例如,/some/path/),這樣無論從哪個頁面呼叫註冊程式碼,解析後的範圍都是相同的。service worker 註冊的預設 scope 是 service worker 指令碼所在目錄(相對於 scriptURL 解析 ./)。

範圍應該用於指定與 service worker 相同目錄或更深層目錄下的文件。如果您需要更廣泛的範圍,可以透過 HTTP Service-Worker-Allowed 標頭來實現。有關擴充套件 service worker 預設範圍的資訊,請參閱 示例 部分。

type

一個字串,指定要建立的工作程式的型別。有效值為:

'classic'

載入的 service worker 是標準指令碼。這是預設值。

'module'

載入的 service worker 是 ES 模組,並且 import 語句在 worker 上下文中可用。有關 ES 模組相容性資訊,請參閱 ServiceWorker 介面的瀏覽器相容性資料表

updateViaCache

一個字串,指示在更新期間如何使用 HTTP 快取來處理 service worker 指令碼資源。注意:這僅指 service worker 指令碼及其匯入,而不指這些指令碼獲取的其他資源。

'all'

將為主要指令碼和所有匯入的指令碼查詢 HTTP 快取。如果在 HTTP 快取中找不到新鮮條目,則從網路獲取指令碼。

'imports'

將為匯入的指令碼查詢 HTTP 快取,但主要指令碼將始終從網路更新。如果在 HTTP 快取中找不到匯入的指令碼的新鮮條目,則從網路獲取它們。

'none'

不會為主要指令碼或其匯入的指令碼使用 HTTP 快取。所有 service worker 指令碼資源都將從網路更新。

返回值

一個 Promise,它解析為一個 ServiceWorkerRegistration 物件。

異常

TypeError

scriptURLscope URL 發生錯誤。如果 URL 無法解析為有效 URL,或使用了非 http:https 的協議,則可能發生此情況。如果 scriptURL 不是 TrustedScriptURL,並且這是站點 Trusted Types Policy 的要求,也可能發生此情況。

如果 scriptURLscope URL 路徑包含不區分大小寫的 ASCII "%2f"(*)或 "%5c"(=),則也會引發該異常。

SecurityError DOMException

scriptURL 不是一個潛在可信的源,例如 localhosthttps URL。scriptURL 和範圍與註冊頁面不是同源的。

示例

應將下面的示例結合起來閱讀,以瞭解 service worker 範圍如何應用於頁面。

使用預設範圍註冊 service worker

以下示例透過省略 scope 的值來使用其預設值,將其設定為與指令碼 URL 相同的位置。

假設 service worker 程式碼位於 example.com/sw.js,註冊程式碼位於 example.com/index.html。service worker 程式碼將控制 example.com/index.html 以及其下的頁面,例如 example.com/product/description.html

js
if ("serviceWorker" in navigator) {
  // Register a service worker hosted at the root of the
  // site using the default scope.
  navigator.serviceWorker.register("/sw.js").then(
    (registration) => {
      console.log("Service worker registration succeeded:", registration);
    },
    (error) => {
      console.error(`Service worker registration failed: ${error}`);
    },
  );
} else {
  console.error("Service workers are not supported.");
}

請注意,我們已相對於站點根目錄而非當前頁面註冊了 scriptURL。這允許從任何頁面使用相同的註冊程式碼。

使用顯式預設範圍註冊 service worker

下面的程式碼幾乎相同,只是我們使用 { scope: "/" } 顯式指定了範圍。我們將範圍指定為站點相對路徑,以便可以從站點的任何位置使用相同的註冊程式碼。

js
if ("serviceWorker" in navigator) {
  // declaring scope manually
  navigator.serviceWorker.register("./sw.js", { scope: "/" }).then(
    (registration) => {
      console.log("Service worker registration succeeded:", registration);
    },
    (error) => {
      console.error(`Service worker registration failed: ${error}`);
    },
  );
} else {
  console.error("Service workers are not supported.");
}

此範圍與預設範圍相同,因此註冊適用於與上一個示例完全相同的頁面。請注意,如果我們在上一個示例之後執行此程式碼,瀏覽器應該會識別出我們正在更新現有註冊而不是新的註冊。

使用頁面相對 URL 註冊 service worker

沒有什麼阻止您使用頁面相對 URL,只是這使得移動頁面變得更加困難,而且這樣做很容易意外建立不需要的註冊。

在此示例中,service worker 程式碼位於 example.com/product/sw.js,註冊程式碼位於 example.com/product/description.html。我們為 scriptURLscope 使用了相對於當前目錄的 URL,當前目錄是呼叫 register() 的頁面的基礎 URL(example.com/product/)。service worker 適用於 example.com/product/ 下的資源。

js
if ("serviceWorker" in navigator) {
  // declaring scope manually
  navigator.serviceWorker.register("./sw.js", { scope: "./" }).then(
    (registration) => {
      console.log("Service worker registration succeeded:", registration);
    },
    (error) => {
      console.error(`Service worker registration failed: ${error}`);
    },
  );
} else {
  console.error("Service workers are not supported.");
}

使用 Service-Worker-Allowed 擴充套件 service worker 範圍

除非伺服器在 service worker 指令碼上使用 Service-Worker-Allowed 標頭指定了更廣泛的最大範圍,否則 service worker 的範圍不能比其自身位置更廣。當您需要比預設值更窄的範圍時,請使用 scope 選項。

以下程式碼如果包含在站點根目錄的 example.com/index.html 中,則僅適用於 example.com/product 下的資源。

js
if ("serviceWorker" in navigator) {
  // declaring scope manually
  navigator.serviceWorker.register("./sw.js", { scope: "/product/" }).then(
    (registration) => {
      console.log("Service worker registration succeeded:", registration);
    },
    (error) => {
      console.error(`Service worker registration failed: ${error}`);
    },
  );
} else {
  console.error("Service workers are not supported.");
}

如上所述,伺服器可以透過在服務 sw.js 時設定 Service-Worker-Allowed 標頭來更改預設範圍。這允許 scope 選項設定在 service worker 位置定義的路徑之外。

如果以下程式碼包含在 example.com/product/index.html 中,並且伺服器在服務 sw.js 時將 Service-Worker-Allowed 標頭設定為 /https://example.com/,則它將適用於 example.com 下的所有資源。如果伺服器未設定該標頭,則請求的 scope 過寬,導致 service worker 註冊失敗。

js
if ("serviceWorker" in navigator) {
  // Declaring a broadened scope
  navigator.serviceWorker.register("./sw.js", { scope: "/" }).then(
    (registration) => {
      // The registration succeeded because the Service-Worker-Allowed header
      // had set a broadened maximum scope for the service worker script
      console.log("Service worker registration succeeded:", registration);
    },
    (error) => {
      // This happens if the Service-Worker-Allowed header doesn't broaden the scope
      console.error(`Service worker registration failed: ${error}`);
    },
  );
} else {
  console.error("Service workers are not supported.");
}

規範

規範
Service Workers
# navigator-service-worker-register

瀏覽器相容性

另見