OpenPWAStore
返回 News
Guide · May 20, 2026

WebSocket 需要 Service Worker 感知,才能在已安装的 PWA 中持续存活

最小化你的 PWA 不应该中断实时功能。Service Workers 让 WebSocket 持久化成为可能。

OpenPWA Editorial2 min read
WebSocket 需要 Service Worker 感知,才能在已安装的 PWA 中持续存活 cover

为什么 WebSocket 生命周期是安装问题

用户安装实时应用(聊天、协作、实时仪表板)时,期望它们真正实时。当 WebSocket 连接在最小化、后台或挂起时断开,应用就在「始终在线」的核心承诺上失败了。MDN 的 Service Worker API 文档 表明,Service Workers 可以在主线程挂起时维持网络上下文——这是保持基于 WebSocket 的 PWA 功能正常的关键。

失败流程:没有 Service Worker 集成时会发生什么

  1. 用户安装聊天应用
  2. 应用在主线程建立 WebSocket
  3. 用户最小化应用(iOS)或切换标签页(桌面)
  4. 浏览器节流主线程定时器
  5. WebSocket 在不活动超时后关闭
  6. 用户返回应用:没有新消息,需要重新连接
  7. 用户责怪应用,将其删除

成功流程:Service Worker 管理的 WebSocket 生命周期

  1. PWA 通过 Service Worker 建立 WebSocket
  2. Service Worker 即使主线程休眠也保持连接
  3. 新消息在 Service Worker 存储中排队
  4. 用户唤醒应用:消息同步瞬间完成
  5. 应用感觉"活着",用户保持安装

实现模式

模式 1:Service Worker 客户端路由

// 主线程中
const ws = new WebSocket('wss://api.example.com/realtime');
ws.onmessage = (event) => {
  // 显示消息
};

// 更好的方式:通过 Service Worker 路由
navigator.serviceWorker.addEventListener('message', (event) => {
  if (event.data.type === 'ws-message') {
    // 显示来自 Service Worker 的消息
  }
});

模式 2:Service Worker WebSocket 管理

// Service Worker 中
let wsConnection;

self.addEventListener('message', (event) => {
  if (event.data.action === 'connect') {
    wsConnection = new WebSocket(event.data.url);
    wsConnection.onmessage = (msg) => {
      // 在 IndexedDB 中存储消息
      // 通知所有客户端
      self.clients.matchAll().then(clients => {
        clients.forEach(client => client.postMessage({
          type: 'ws-message',
          payload: msg.data
        }));
      });
    };
  }
});

模式 3:后台同步用于重连

// Service Worker 中
self.addEventListener('sync', (event) => {
  if (event.tag === 'websocket-reconnect') {
    event.waitUntil(reconnectWebSocket());
  }
});

async function reconnectWebSocket() {
  // 使用指数退避尝试重连
}

平台特定的 WebSocket 行为

iOS Safari

  • 最小化时 WebSocket 连接被激进节流
  • Service Worker 将连接延长大约 5-10 分钟
  • 后台获取防止完全连接丢失
  • 需要用户交互背景音频例外

Chrome/Edge(桌面)

  • 标签页后台后约 30-120 秒开始 WebSocket 节流
  • Service Worker 延长至约 5 分钟以上才关闭
  • 资源限制时发生标签页丢弃
  • 通知权限延长后台生命周期

Android Chrome

  • 节流不如 iOS 激进
  • Service Worker 在大多数状态下维持 WebSocket
  • 省电模式仍会强制关闭
  • 前台服务(通过已安装应用包装器)进一步延长

WebSocket 不是万能药

并非每个实时功能都需要 WebSocket:

  • 30+ 秒间隔的更新,轮询完全够用
  • 推送通知更适合高延迟、低频事件
  • Server-Sent Events (SSE) 简化单向流式传输
  • 周期性后台同步可以批处理离线更新

仅在这些情况下实施 WebSocket:

  • 毫秒级延迟确实重要(协作、游戏)
  • 需要双向同时通信
  • 连接安全 / 隐私规则禁止轮询
  • 用户明确期望"实时"行为

隐私和权限约束

实时连接有边缘情况:

  • WebSocket 数据绕过标准缓存清除
  • IndexedDB 存储的消息跨站点数据擦除持续存在
  • 用户驱动的登出必须显式关闭连接
  • 绕过用户代理节流可能触发隐私警告

始终提供:

  1. 设置中清晰的实时开关
  2. 实时数据使用指标
  3. 真正终止连接的断开按钮
  4. 解释持续化行为的隐私说明

测量检查清单

使用以下指标监控 WebSocket 生命周期:

  • 连接持续时间(节流前)
  • 唤醒后重连成功率
  • 消息传递延迟(主线程 vs Service Worker)
  • 持续连接的电池影响
  • 启用实时后的数据使用增长

下一步

从简单的 Service Worker 重连模式开始,测量连接稳定性,然后对关键实时功能升级到完整的 Service Worker 管理的 WebSocket 路由。