> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.onesignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# OneSignal service worker

> 设置和配置 OneSignalSDKWorker.js 文件，让您的网站能够通过 OneSignal 接收和显示网页推送通知。

OneSignal service worker（`OneSignalSDKWorker.js`）是托管在您服务器上的 JavaScript 文件，是网页推送通知的必要组件。它使您的网站能够接收和显示通知，即使用户不在您的页面上也能正常运行。

<Frame caption="OneSignal service worker 处理推送通知的方式">
  <img src="https://mintcdn.com/onesignal/MUgio66t0sYhGEvj/images/docs/67882a5-onesignsal-service-worker.jpg?fit=max&auto=format&n=MUgio66t0sYhGEvj&q=85&s=e0b50cfe6ccc36c1b2b6d36219b6e3ad" alt="Diagram showing the OneSignal service worker receiving a push event and displaying a notification" width="2016" height="949" data-path="images/docs/67882a5-onesignsal-service-worker.jpg" />
</Frame>

<Note>
  如果您使用我们的 WordPress 插件，service worker 会自动添加。请跳过本指南并返回 [WordPress 设置](./wordpress)。
</Note>

## Service worker 设置

为 OneSignal 推送通知创建专用的 `OneSignalSDKWorker.js` 文件。如果您的网站已有 service worker 并希望使用单个文件，请改为参阅[合并多个 service worker](#combining-multiple-service-workers)。

<Steps>
  <Step title="下载或创建 OneSignalSDKWorker.js">
    在 [Web SDK 设置](./web-sdk-setup)过程中从 OneSignal 仪表板下载该文件，或[从 GitHub 下载](https://github.com/OneSignal/OneSignal-Website-SDK/files/11480764/OneSignalSDK-v16-ServiceWorker.zip)。

    或者，创建一个名为 `OneSignalSDKWorker.js` 的文件，包含以下单行代码：

    ```javascript theme={null}
    importScripts("https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.sw.js");
    ```

    <Note>
      如有需要，您可以重命名该文件（例如改为 `onesignalsdkworker.js`）。如果这样做，只需将本指南中的 `OneSignalSDKWorker.js` 替换为您的文件名即可。
    </Note>
  </Step>

  <Step title="上传到您的 Web 服务器">
    将 `OneSignalSDKWorker.js` 放置在服务器上，使其可通过 HTTPS 公开访问。该文件不得要求身份验证或登录才能访问。

    **推荐方式：** 将文件托管在永远不会提供页面的专用子目录中，例如 `/push/onesignal/`。这样可以避免与网站上其他 service worker 发生冲突（例如 PWA 或 AMP service worker），并保持 URL 路径稳定。

    * 示例：`https://yoursite.com/push/onesignal/OneSignalSDKWorker.js`

    **替代方式：** OneSignal Web SDK 默认在网站根目录查找该文件（`https://yoursite.com/OneSignalSDKWorker.js`）。您可以将文件上传到根目录，但可能与其他需要根作用域的 service worker 发生冲突。例如，如果您使用 PWA，请将 `OneSignalSDKWorker.js` 放在子目录中。

    <Warning>
      请选择**永久**的 URL 路径。一旦浏览器在给定 URL 注册了 service worker，更改该 URL 需要进行[迁移](#migration-guide)。
    </Warning>
  </Step>

  <Step title="验证文件可访问性">
    在浏览器中导航到文件 URL（例如 `https://yoursite.com/push/onesignal/OneSignalSDKWorker.js`）。

    您应该看到第 1 步中的 `importScripts` 行：

    <Frame caption="浏览器中预期显示的 service worker 文件内容">
      <img src="https://mintcdn.com/onesignal/eSOC1PsvyAo3Gten/images/push/service-worker-code-example.png?fit=max&auto=format&n=eSOC1PsvyAo3Gten&q=85&s=3add122d37c9f12a39f1d7e3d40eeaba" alt="Browser displaying the single importScripts line inside OneSignalSDKWorker.js" width="1678" height="322" data-path="images/push/service-worker-code-example.png" />
    </Frame>

    如果您看到 404 错误、空白页面或登录提示，则说明文件未正确上传或位于身份验证之后。
  </Step>

  <Step title="配置 SDK 路径（仅限子目录）">
    如果您将文件放置在网站根目录，则无需额外配置——直接跳到下一步。

    如果您将文件放置在子目录中，请告知 SDK 文件位置：

    #### 典型网站设置

    1. 在 OneSignal 仪表板中，进入**设置 > Push & In-App > Web 设置**。
    2. 在**高级推送设置**下，启用**自定义 service worker 路径和文件名**。

    <Frame caption="仪表板中的 service worker 路径配置">
      <img src="https://mintcdn.com/onesignal/npQH4TNAoIbyiAie/images/dashboard/service-worker-configuration-typical-site-setup.png?fit=max&auto=format&n=npQH4TNAoIbyiAie&q=85&s=0bc69998eea5273d287af408c6e925b3" alt="OneSignal dashboard fields for service worker path, filename, and registration scope" width="1840" height="794" data-path="images/dashboard/service-worker-configuration-typical-site-setup.png" />
    </Frame>

    | 字段                                    | 说明                                                          | 示例                      |
    | ------------------------------------- | ----------------------------------------------------------- | ----------------------- |
    | **Path to service worker files**      | 托管 `OneSignalSDKWorker.js` 的目录。                             | `/push/onesignal/`      |
    | **Service worker filename**           | `.js` 文件的名称。                                                | `OneSignalSDKWorker.js` |
    | **Service worker registration scope** | service worker 控制的 URL 路径。必须位于文件托管目录或其子目录。请使用永远不会提供用户页面的路径。 | `/push/onesignal/`      |

    #### 自定义代码设置

    在您的 [`OneSignal.init()`](./web-push-custom-code-setup) 调用中传入 `serviceWorkerPath` 和 `serviceWorkerParam`：

    ```html theme={null}
    <script src="https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.page.js" defer></script>
    <script>
      window.OneSignalDeferred = window.OneSignalDeferred || [];
      window.OneSignalDeferred.push(async function(OneSignal) {
        await OneSignal.init({
          appId: "YOUR_APP_ID",
          serviceWorkerPath: "push/onesignal/OneSignalSDKWorker.js",
          serviceWorkerParam: { scope: "/push/onesignal/" },
        });
      });
    </script>
    ```

    | 参数                         | 说明                                                          | 示例                                       |
    | -------------------------- | ----------------------------------------------------------- | ---------------------------------------- |
    | `serviceWorkerPath`        | 从网站根目录到 `.js` 文件的相对路径（不含开头斜杠）。                              | `"push/onesignal/OneSignalSDKWorker.js"` |
    | `serviceWorkerParam.scope` | service worker 控制的 URL 路径。必须位于文件托管目录或其子目录。请使用永远不会提供用户页面的路径。 | `"/push/onesignal/"`                     |
  </Step>

  <Step title="查看 service worker 要求">
    `OneSignalSDKWorker.js` 文件必须满足以下所有要求。如有任何要求未满足，推送通知将无法正常工作。

    | 要求          | 详情                                                                                                                                                                         |
    | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | **可公开访问**   | 在浏览器中导航到文件 URL，确认可以看到 JavaScript 代码。                                                                                                                                       |
    | **正确的内容类型** | 服务器必须返回 `Content-Type: application/javascript; charset=utf-8`。                                                                                                             |
    | **同源**      | 文件必须托管在与您网站相同的域名上。不允许使用 CDN 和子域名。请参阅 [MDN：注册您的 worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers#Registering_your_worker)。 |
    | **HTTPS**   | Service worker 需要安全上下文。开发期间 `localhost` 是唯一的例外。                                                                                                                            |

    <Check>
      Service worker 设置完成。
    </Check>

    <Card title="Web SDK 设置" icon="browsers" href="./web-sdk-setup">
      继续使用 Web SDK 设置指南了解后续步骤。
    </Card>
  </Step>
</Steps>

***

## 合并多个 service worker

网站上的每个 service worker 文件都注册在一个**作用域**——一个决定其控制哪些页面的 URL 路径。在给定作用域只能有一个 service worker 处于活跃状态。如果您已经有一个 service worker（例如 PWA 或缓存 worker）并且希望 OneSignal 共享同一文件，可以将它们合并。

<Warning>
  将 service worker 保存在具有独立作用域的独立文件中更易于维护且可避免冲突。仅当您的设置需要单个 service worker 文件时才进行合并。
</Warning>

若要合并，请将 OneSignal `importScripts` 行添加到您**现有**的 service worker 文件中：

```javascript theme={null}
importScripts("https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.sw.js");
importScripts("https://yoursite.com/your-other-service-worker.js");
```

合并后，更新 OneSignal 配置以指向您现有的 service worker 文件。使用合并文件的路径和文件名，按照[第 4 步：配置 SDK 路径](#step-4-configure-the-sdk-path-subdirectory-only)进行操作。

***

## 迁移指南

本节适用于需要更改 service worker 文件路径、文件名或作用域的现有 OneSignal 客户。除非您有特定原因需要更改当前配置，否则请勿执行这些步骤。

<Accordion title="何时以及如何迁移您的 service worker">
  **迁移原因：**

  * 根作用域 OneSignal service worker 与渐进式网页应用（PWA）冲突
  * Service worker 与 AMP 或其他缓存 service worker 冲突
  * 安全策略禁止在根作用域运行第三方 service worker 代码

  **选项 1：仅更改作用域（推荐）**

  仅更改作用域是最安全的迁移方式。文件保持在当前 URL，现有订阅者可以不间断地继续接收通知。

  **如果您的文件仅包含 OneSignal 代码**

  确认 `OneSignalSDKWorker.js` 仅包含：

  ```javascript theme={null}
  importScripts("https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.sw.js");
  ```

  按照[第 4 步：配置 SDK 路径](#step-4-configure-the-sdk-path-subdirectory-only)中的描述，使用仪表板或 `serviceWorkerParam` 更新作用域。无需其他更改。

  <Warning>
    如果 `OneSignalSDKWorker.js` 今天**没有**托管在您的域名根目录，您必须继续使用 `Service-Worker-Allowed` 响应头在当前 URL 托管该文件至少一年。请在您的后端代码或内部文档中添加注释，以防文件被意外删除。
  </Warning>

  **如果您的文件包含 OneSignal + 其他代码**

  您的 service worker 可能包含额外的 `importScripts` 调用（例如，来自[合并多个 service worker](#combining-multiple-service-workers) 指南）。如果您当前的设置仍然有效，请**保持原样**——拆分合并的 service worker 需要两阶段发布。

  如果您必须分离它们：

  <Steps>
    <Step title="向现有文件添加保留注释">
      在当前 service worker 中 OneSignal `importScripts` 行的上方添加：

      ```javascript theme={null}
      // KEEP until YYYY-MM-DD: Required for push delivery to subscribers who have not revisited.
      importScripts("https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.sw.js");
      ```

      日期至少设置为**一年**后。
    </Step>

    <Step title="创建新的专用 OneSignal service worker">
      在子目录（例如 `/push/onesignal/`）中创建仅包含以下内容的 `OneSignalSDKWorker.js`：

      ```javascript theme={null}
      importScripts("https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.sw.js");
      ```
    </Step>

    <Step title="更新 OneSignal 配置">
      按照[第 4 步：配置 SDK 路径](#step-4-configure-the-sdk-path-subdirectory-only)中的描述，使用仪表板或 `OneSignal.init()` 设置新路径和作用域。
    </Step>

    <Step title="等待订阅者迁移">
      新访客和回访者会自动使用新的 service worker 进行注册。等待至少一年，让大多数现有订阅者重新访问您的网站。
    </Step>

    <Step title="清理">
      [删除不活跃用户](./delete-users)（超过您选择的保留期限的用户），然后从原始 service worker 文件中移除 OneSignal `importScripts` 行。
    </Step>
  </Steps>

  **选项 2：更改文件名或文件位置**

  更改文件名或目录更为复杂，因为浏览器从最初注册时的 URL 获取 service worker。尚未重新访问您网站的订阅者仍引用旧 URL。

  <Warning>
    您必须继续在旧 URL 托管原始文件至少一年。删除该文件会导致浏览器尝试更新 service worker 时出现 404 错误，受影响的订阅者将停止接收通知。
  </Warning>

  **如果您的文件仅包含 OneSignal 代码**

  <Steps>
    <Step title="向旧文件添加保留注释">
      ```javascript theme={null}
      // KEEP until YYYY-MM-DD: Required for push delivery to subscribers still on the old service worker URL.
      importScripts("https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.sw.js");
      ```
    </Step>

    <Step title="在新位置创建新文件">
      将 `OneSignalSDKWorker.js`（或您选择的文件名）放置在新目录中，包含：

      ```javascript theme={null}
      importScripts("https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.sw.js");
      ```
    </Step>

    <Step title="更新 OneSignal 配置">
      按照[第 4 步：配置 SDK 路径](#step-4-configure-the-sdk-path-subdirectory-only)中的描述设置新路径、文件名和作用域。
    </Step>

    <Step title="等待订阅者迁移">
      新访客和回访者会自动使用新文件进行注册。等待至少一年。
    </Step>

    <Step title="清理">
      [删除不活跃用户](./delete-users)（超过您保留期限的用户），然后删除旧文件。
    </Step>
  </Steps>

  **如果您的文件包含 OneSignal + 其他代码**

  按照上方**选项 1：仅更改作用域**中的步骤操作。流程相同。
</Accordion>

***

## 常见问题

### 为什么我的 service worker 返回 404？

文件不在 SDK 预期的 URL 位置。在浏览器中导航到完整的文件 URL 以确认其可访问性。如果您将文件放置在子目录中，请验证 `serviceWorkerPath`（自定义代码）或仪表板路径设置与实际文件位置匹配——包括目录和文件名。

### 为什么我移动 service worker 文件后通知不再显示？

现有订阅者仍然引用旧的 service worker URL。每次推送到达时，浏览器都会获取已注册的 URL（最多缓存 24 小时）。如果旧 URL 返回 404，这些订阅者将无法收到通知。继续托管旧文件至少一年，同时订阅者通过重新访问您的网站自然迁移。请参阅[迁移指南](#migration-guide)和[网页推送通知未显示](./notifications-not-shown-web-push)指南。

### 我可以在 CDN 或子域名上托管 service worker 吗？

不可以。浏览器要求 service worker 与注册它的页面来自同一源。文件必须在您的主域名上——不能使用 CDN、子域名或不同域名。

### 为什么我的 PWA 与 OneSignal service worker 冲突？

两者可能都注册在根作用域（`/`），而在特定作用域只能注册一个 service worker。将 OneSignal service worker 移至子目录作用域（例如 `/push/onesignal/`），使您的 PWA 保留对根作用域的控制，或按照[合并多个 service worker](#combining-multiple-service-workers) 中的描述合并 service worker。

### 我可以重命名 OneSignalSDKWorker.js 文件吗？

可以。如果您的服务器需要特定的命名规范（例如全小写），可以将文件重命名为 `onesignalsdkworker.js` 之类的名称。如果这样做，请在您的 OneSignal 配置中更新文件名——在仪表板的 **Service worker filename** 字段中，或在 `OneSignal.init()` 调用的 `serviceWorkerPath` 参数中。详情请参阅[第 4 步](#step-4-configure-the-sdk-path-subdirectory-only)。

### 我的服务器应该为 service worker 文件返回什么内容类型？

服务器必须返回 `Content-Type: application/javascript; charset=utf-8`。某些服务器或 CDN 配置可能返回不正确的 MIME 类型，导致浏览器拒绝 service worker 注册。
