目录 (Outline)
- 一、 实时通信的「旧伤」:为什么 Node.js 一直没有内置 WebSocket?
- 二、 Node.js 22 原生 WebSocket:基于 Web 标准的设计
- 三、 快速上手:构建你的第一个原生 WebSocket 客户端
- 四、 核心优势:零依赖、内存安全与性能表现
- 五、 实战 1:处理二进制数据 (Blob 与 ArrayBuffer)
- 六、 实战 2:WebSocket 与 Node.js Streams 的结合
- 七、 总结:Node.js 内置 API 的「去第三方化」趋势
一、 实时通信的「旧伤」:为什么 Node.js 一直没有内置 WebSocket?
1. 历史局限
长期以来,Node.js 开发者不得不依赖第三方库:
- ws:最流行、性能最强的库。
- socket.io:提供高级抽象,但也带来了巨大的包体积。
2. 痛点
- 版本冲突:不同库之间的 WebSocket 协议版本可能存在细微差异。
- 维护成本:第三方库的漏洞修复和版本升级增加了维护负担。
- 跨平台一致性:Node.js 客户端与浏览器端 WebSocket API 的巨大差异。
二、 Node.js 22 原生 WebSocket:基于 Web 标准的设计
Node.js 22 引入的 WebSocket 构造函数完全遵循 W3C WebSocket API 标准。
核心改进
- 全局可用:无需
require或import,直接在全局作用域使用。 - 浏览器兼容:代码可以直接在浏览器和 Node.js 之间复用。
- 基于 Undici:底层使用了 Node.js 高性能的 HTTP/1.1 客户端 Undici 实现。
三、 快速上手:构建你的第一个原生 WebSocket 客户端
代码示例
const socket = new WebSocket('wss://echo.websocket.org');
// 监听连接开启
socket.onopen = () => {
console.log('Connected to server!');
socket.send('Hello Node.js 22!');
};
// 监听消息接收
socket.onmessage = (event) => {
console.log('Received:', event.data);
};
// 监听关闭
socket.onclose = () => {
console.log('Connection closed.');
};
// 监听错误
socket.onerror = (error) => {
console.error('WebSocket Error:', error);
};
四、 核心优势:零依赖、内存安全与性能表现
1. 零依赖
内置 WebSocket 减少了 node_modules 的体积,并降低了供应链攻击的风险。
2. 内存安全
由于是 C++ 层面实现的原生对象,其内存管理比纯 JS 实现的库更加高效,尤其在处理海量并发连接时。
五、 实战 1:处理二进制数据 (Blob 与 ArrayBuffer)
原生 WebSocket 对二进制数据的支持非常出色。
代码示例
socket.binaryType = 'arraybuffer';
socket.onmessage = (event) => {
if (event.data instanceof ArrayBuffer) {
const view = new DataView(event.data);
console.log('Received binary data size:', view.byteLength);
}
};
六、 实战 2:WebSocket 与 Node.js Streams 的结合
虽然原生 WebSocket API 是基于事件的,但我们可以轻松地将其封装为 Node.js 的 Readable 或 Writable 流。
封装思路
- Readable Stream:将
onmessage数据push到流中。 - Writable Stream:将
write操作映射到socket.send。
这种方式让 WebSocket 能够完美融入 Node.js 的流式数据处理生态。
七、 总结:Node.js 内置 API 的「去第三方化」趋势
从内置 .env 支持、原生测试运行器到现在的 WebSocket 客户端,Node.js 正在努力减少对外部生态的依赖。对于开发者来说,这意味着更稳定的基础架构和更低的学习成本。