Electron 43.2.0 引入 WHATWG 兼容的 net.WebSocket

2026-07-23 15 预计阅读时间: 1 分钟
来源: oschina.net AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:6 分钟

Electron 43.2.0 已发布。这次更新中值得桌面应用开发者关注的一项能力,是新增 WHATWG 兼容的 net.WebSocket。Electron 应用可以在主进程中使用更接近浏览器标准的 WebSocket 接口,同时继续依托 Electron 的网络栈处理连接。

为什么主进程 WebSocket 值得关注

Electron 基于 Chromium 和 Node.js,可用 JavaScript、HTML 与 CSS 构建 macOS、Windows 和 Linux 桌面应用。实际项目通常同时存在两类网络代码:渲染进程使用浏览器 API,主进程则使用 Node.js 库。

新增的 net.WebSocket 缩小了这两套编程模型之间的差异。由于接口与 WHATWG WebSocket 兼容,开发者可以继续使用熟悉的事件和状态模型,例如:

  • 通过 open 事件确认连接建立;
  • 调用 send() 发送文本或二进制消息;
  • message 事件中读取服务端数据;
  • 监听 errorclose,完成错误记录与资源清理。

这对于实时通知、任务进度、设备状态同步和协作编辑等桌面场景尤其有用。共享代码仍需谨慎:主进程与渲染进程的安全边界、代理配置和生命周期并不相同,接口相似不代表运行环境完全一致。

可以这样实践:连接本地 WebSocket 服务

下面是一个可运行的最小项目。示例使用 ws 创建本地回显服务,再通过 Electron 43.2.0 的 net.WebSocket 连接它,因此不依赖公网测试服务。

创建 package.json

{
  "name": "electron-net-websocket-demo",
  "version": "1.0.0",
  "private": true,
  "main": "main.js",
  "scripts": {
    "start": "electron ."
  },
  "devDependencies": {
    "electron": "43.2.0",
    "ws": "^8.18.0"
  }
}

创建 main.js

const { app, net } = require('electron');
const { WebSocketServer } = require('ws');

app.whenReady().then(() => {
  const server = new WebSocketServer({ port: 0 });

  server.on('connection', (socket) => {
    socket.on('message', (data) => {
      socket.send(`echo: ${data.toString()}`);
    });
  });

  server.on('listening', () => {
    const { port } = server.address();
    const socket = new net.WebSocket(`ws://127.0.0.1:${port}`);

    socket.addEventListener('open', () => {
      console.log('WebSocket connected');
      socket.send('hello from Electron');
    });

    socket.addEventListener('message', (event) => {
      console.log('Received:', event.data);
      socket.close(1000, 'demo complete');
    });

    socket.addEventListener('error', (event) => {
      console.error('WebSocket error:', event);
    });

    socket.addEventListener('close', (event) => {
      console.log(`Closed: code=${event.code}, reason=${event.reason}`);
      server.close(() => app.quit());
    });
  });
});

安装并运行:

npm install
npm start

正常情况下,终端会依次输出连接成功、回显消息和关闭状态。接入真实服务时,将 ws://127.0.0.1:${port} 替换为自己的 wss:// 地址,并删除示例中的本地 WebSocketServer

不要把连接管理塞进每个窗口

在多窗口 Electron 应用中,可以让主进程持有唯一 WebSocket 连接,再通过 IPC 向经过授权的渲染进程分发消息。这样能够避免每打开一个窗口就创建一条连接,也便于集中处理认证、重连和日志。

不要直接向页面暴露整个 ipcRenderer 或底层 socket。可以通过 preload 脚本只开放有限的方法:

const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('realtime', {
  send: (message) => ipcRenderer.invoke('realtime:send', message),
  onMessage: (callback) => {
    const listener = (_event, message) => callback(message);
    ipcRenderer.on('realtime:message', listener);
    return () => ipcRenderer.removeListener('realtime:message', listener);
  }
});

这段代码只是推荐的边界设计示例;主进程仍需校验消息类型、长度和发送方身份。对于包含访问令牌的连接,也应避免将完整 URL、请求头或服务端消息写入普通日志。

升级时检查这些边界

采用 Electron 43.2.0 前,建议完成以下检查:

  • 锁定 Electron 版本并在三个目标平台执行冒烟测试;
  • 验证企业代理、系统证书以及 wss:// 握手行为;
  • 为断网、休眠唤醒和服务端重启设计带退避的重连策略;
  • 设置消息大小上限,并验证服务端发送的 JSON 或二进制数据;
  • 在窗口关闭和应用退出时清理事件监听器与连接;
  • 阅读完整发布说明,确认同一版本中的修复和兼容性变化。

net.WebSocket 的主要价值不是少安装一个依赖,而是让 Electron 主进程采用更标准化的实时通信接口。是否立即迁移,应取决于现有网络库的稳定性、代理需求和测试覆盖;已经成熟运行的连接层没有必要只为统一 API 而仓促重写。


相关推荐