Skip to main content

难点:Electron WebSocket 保活

在 macOS 上,Electron 应用切换到后台后 WebSocket 连接中断,主要是因为 Chromium 为了节能,会主动挂起后台的渲染进程,暂停其 JavaScript 执行。

要解决这个问题,核心思路是将 WebSocket 连接从易被挂起的渲染进程,转移到生存周期更稳定的主进程。同时,配合一些系统层面的配置,可以最大程度保证连接的稳定性。

以下是几种可行的方法,可以组合使用:

🧠 核心方案:在主进程中管理 WebSocket 连接

这是最根本、最推荐的解决方案。渲染进程(网页)的生命周期短暂,页面刷新或关闭都会导致其中的 WebSocket 连接断开。而主进程(main.js)是 Node.js 环境,独立于窗口运行,生命周期与应用本身一致,是管理长连接的理想场所。

  1. 在主进程中创建并管理 WebSocket:推荐使用 Node.js 的 ws 库,它功能更强大,更易于控制。在主进程中维护一个 WebSocket 单例。
  2. 通过 IPC 与渲染进程通信:使用 Electron 的 ipcMainipcRenderer 模块,并配合 contextBridgepreload.js 中安全地暴露 API。这样,渲染进程就可以通过 IPC 触发主进程的 WebSocket 操作(如发送消息),并监听来自主进程的消息推送。

🛠️ 辅助方案:配置与机制

除了架构调整,还可以配合以下方法,进一步确保连接稳定。

  • 禁用渲染进程的后台节流 (backgroundThrottling):在创建 BrowserWindow 时,将 webPreferences 中的 backgroundThrottling 设置为 false。这可以指示 Chromium 不要主动限制该窗口后台时的性能,从而让其中的 JavaScript(如果仍有)能继续运行。

    // 在主进程中
    const mainWindow = new BrowserWindow({
    // ... 其他配置
    webPreferences: {
    // ... 其他偏好
    backgroundThrottling: false, // 关键配置
    }
    });
  • 防止应用被系统挂起 (powerSaveBlocker):macOS 在屏幕关闭或系统空闲时可能会暂停应用。可以使用 Electron 的 powerSaveBlocker 模块来阻止这一行为。

    // 在主进程中
    const { powerSaveBlocker } = require('electron');
    // 启动阻止器,防止应用被挂起
    const blockerId = powerSaveBlocker.start('prevent-app-suspension');
    // 在应用退出时记得停止阻止器
    app.on('will-quit', () => {
    if (powerSaveBlocker.isStarted(blockerId)) {
    powerSaveBlocker.stop(blockerId);
    }
    });

    prevent-app-suspension 模式会阻止应用被暂停,同时允许屏幕关闭,非常适合后台下载或保持连接等场景。

  • 实现心跳与自动重连机制:无论采用何种保活策略,网络波动或服务端重启都可能导致连接断开。因此,心跳与自动重连是必不可少的

    • 心跳 (Heartbeat):在主进程中,定时(如每30秒)通过 WebSocket 向服务端发送一个轻量级的 ping 消息,服务端回复 pong,以保持连接活跃。
    • 自动重连 (Auto-Reconnect):在 WebSocket 的 oncloseonerror 事件中,加入指数退避的重连逻辑,避免在服务端不可用时频繁重连造成资源浪费。

💎 总结与版本提示

总的来说,保证 Electron 在 macOS 后台 WebSocket 不中断的最佳实践是:

  1. 首要:将 WebSocket 连接放在主进程中管理。
  2. 其次:配置 backgroundThrottling: false
  3. 再次:考虑使用 powerSaveBlocker.start('prevent-app-suspension')
  4. 最后但同样重要:实现心跳与自动重连机制。

另外,在较新版本的 Electron 中,曾修复过一个允许 WebSocket 不被后台化的 flag。虽然这不是一个需要开发者手动配置的选项,但它说明 Electron 团队一直在关注并改进后台连接的问题。因此,将 Electron 升级到最新稳定版也是一个好习惯,可以确保你获得最新的修复和改进。