30秒上手PeerJS:从零搭建第一个WebRTC点对点聊天完整教程
【免费下载链接】peerjsSimple peer-to-peer with WebRTC.项目地址: https://gitcode.com/gh_mirrors/pe/peerjs
PeerJS 是一个基于 WebRTC 的轻量级点对点(P2P)通信库,它把复杂的信令协商、连接建立和浏览器兼容处理全部封装成几行简单 API,让你无需深入理解 SDP 和 ICE 细节,就能快速搭建 WebRTC 点对点聊天、文件传输、音视频通话等应用。本文将带你用不到 30 分钟,从零完成第一个可用的 P2P 文字聊天页面。
为什么 PeerJS 适合新手做第一个 P2P 项目 ⚡
原生 WebRTC API 需要手动处理信令交换(SDP offer/answer)、候选地址收集(ICE candidates)、多浏览器差异适配,代码量往往上千行。PeerJS 的价值在于:
- 极简 API:
new Peer()创建节点,peer.connect()建立数据通道,三行代码完成连接 - 内置信令服务器:默认接入公共信令服务,开箱即用;也可自建 PeerServer 完全托管
- 数据与媒体双通道:同一套 API 既支持
DataConnection(文字、JSON、二进制数据),也支持MediaConnection(音视频流) - 成熟稳定:MIT 协议,核心逻辑见 lib/peer.ts,导出入口在 lib/exports.ts
浏览器支持(来自 README.md):
| Chrome | Edge | Firefox | Safari |
|---|---|---|---|
| 83+ | 83+ | 80+ | 15+ |
提示:Firefox 102+ 才支持 MsgPack/CBOR 序列化,详见 lib/dataconnection/StreamConnection/MsgPack.ts。
安装 PeerJS:npm 一行命令搞定 📦
打开终端执行:
npm install peerjsYarn 用户则运行yarn add peerjs。
如果你希望通读源码、对照本教程学习内部实现,可以先克隆仓库:
git clone https://gitcode.com/gh_mirrors/pe/peerjs cd peerjs && npm install项目关键目录速览:
| 路径 | 作用 |
|---|---|
| lib/peer.ts | Peer 核心类,连接/呼叫/事件的总入口 |
| lib/dataconnection/DataConnection.ts | 数据通道封装(聊天消息走这里) |
| lib/mediaconnection.ts | 音视频媒体连接 |
| lib/negotiator.ts | WebRTC offer/answer 协商管理 |
| lib/socket.ts | 与信令服务器的 WebSocket 通信 |
| e2e/ | 端到端测试页面,含数据收发、错误场景演示 |
建立 P2P 数据通道:只需 5 行核心代码
点对点通信有两个角色:发起方主动连接对方的 Peer ID,接收方监听连接请求。
发起方(Alice):
import { Peer } from "peerjs"; const peer = new Peer(); // 不传 ID,由服务器分配一个随机 ID peer.on("open", (id) => { console.log("我的 Peer ID:", id); // 把这个 ID 告诉对方 }); const conn = peer.connect("对方的-peer-id"); conn.on("open", () => { conn.send("hi!"); // 通道就绪后即可发送 });接收方(Bob):
peer.on("connection", (conn) => { conn.on("data", (data) => { console.log(data); // 收到 'hi!' }); conn.on("open", () => { conn.send("hello!"); // 回复对方 }); });完整的 Peer 配置项(自定义信令服务器地址、端口、TLS、调试级别等)定义在 lib/peer.ts#L25-L68 的PeerOptions中,事件模型集中在 lib/peer.ts#L80-L109。
单页聊天示例:完整可用的文字聊天应用 ✍️
下面是一个可以直接跑起来的单页聊天 Demo(页面引入构建产物dist/peerjs.min.js的方式,与项目自带的 e2e/datachannel/serialization.html 测试页一致)。两个浏览器窗口各打开一份,输入对方 ID 点击"连接",即可互发消息:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <title>PeerJS 点对点聊天</title> </head> <body> <h1>PeerJS 点对点聊天</h1> <div id="status">等待连接…</div> <div id="messages"></div> <input id="peer-id" placeholder="输入对方的 Peer ID" /> <button onclick="connect()">连接</button> <input id="text" placeholder="输入消息" /> <button onclick="send()">发送</button> <script src="/dist/peerjs.min.js"></script> <script> const peer = new Peer(); const status = document.getElementById("status"); const messages = document.getElementById("messages"); let conn; peer.on("open", (id) => { status.textContent = "我的 Peer ID:" + id; }); peer.on("error", (err) => { status.textContent = "出错:" + err.type; }); // 作为被动方:对方主动连过来 peer.on("connection", (c) => { conn = c; c.on("open", () => (status.textContent = "对方已连接")); c.on("data", (text) => append("对方", text)); }); // 作为主动方:我点击连接按钮 function connect() { const otherId = document.getElementById("peer-id").value; conn = peer.connect(otherId); conn.on("open", () => (status.textContent = "连接成功!")); conn.on("data", (text) => append("对方", text)); } function send() { const text = document.getElementById("text").value; if (conn) conn.send(text); append("我", text); } function append(who, text) { const div = document.createElement("div"); div.textContent = who + ":" + text; messages.appendChild(div); } </script> </body> </html>运行方式:npm run build生成dist/peerjs.min.js,再用任意静态服务器打开页面即可。注意只需一方点击"连接",另一方等待即可。
PeerJS 核心事件速查表 📌
掌握下面这张表,日常开发基本够用(来源:lib/peer.ts#L80-L109 与 lib/dataconnection/DataConnection.ts#L15-L26):
| 事件 | 挂载对象 | 触发时机 |
|---|---|---|
open | peer | 与信令服务器建连成功,拿到 Peer ID |
connection | peer | 对方发起数据连接到本机 |
call | peer | 对方发起音视频呼叫 |
open | conn / call | 通道就绪,可开始收发 |
data | conn | 收到对方发来的数据 |
close | conn / peer | 连接被关闭 |
error | peer / conn | 发生错误(peer 级别通常致命,会销毁实例) |
进阶:音视频通话与二进制数据 🎥
语音/视频通话:先拿到本地媒体流,再peer.call()发起,对方用call.answer()接听:
navigator.mediaDevices.getUserMedia({ video: true, audio: true }, (stream) => { const call = peer.call("对方的-peer-id", stream); call.on("stream", (remoteStream) => { videoElement.srcObject = remoteStream; // 播放对方的音视频 }); }); peer.on("call", (call) => { navigator.mediaDevices.getUserMedia({ video: true, audio: true }, (stream) => { call.answer(stream); // 用本地流应答 }); });数据序列化:默认序列化基于 BinaryPack,对象、数组、字符串、二进制均可直接send;项目测试中覆盖了中文、Emoji、大文件、TypedArray 等类型(见 e2e/data.js)。需要压缩传输时可切换 MsgPack 序列化器,在peer.connect(id, { serialization: "msgpack" })中指定。
常见坑与排错清单 🛠️
- Peer ID 冲突:ID 全局唯一,重复会触发
unavailable-id错误。项目自带 e2e/peer/id-taken.html 专门演示"ID 被占用时新连接会安全失败"的场景。 - 生产环境务必用 HTTPS:
getUserMedia和 P2P 连接在非安全上下文(非 HTTPS 的http://页面)下会被浏览器拦截。 - 信令服务器配置:默认连接
0.peerjs.com:443。需要数据自主可控时,可自建 PeerServer 并在new Peer({ host, port, path, secure })中指定。 - 调试技巧:
new Peer({ debug: 3 })打开最详细日志,快速定位协商卡在哪一步,参考 e2e/datachannel/serialization.js。 - 错误几乎都致命:
peer.on("error")触发后实例即被销毁,业务上应重建 Peer 而不是复用。
总结:你的下一步 🚀
到这里,你已经完成了从零开始的 WebRTC 点对点聊天:安装 PeerJS → 创建 Peer 实例 → 建立数据通道 → 实现单页聊天 → 了解事件模型与排错方法。接下来可以按这个路线深入:
- 阅读 lib/negotiator.ts,看看 PeerJS 是如何替你完成 WebRTC 协商的
- 跑一遍端到端测试:
npm test(单元)与npm run e2e(浏览器) - 把聊天升级为文件传输(用
send传File/ArrayBuffer,序列化细节见 e2e/datachannel/ 下的测试用例)
几行代码撬动整条 P2P 通信链路——这就是 PeerJS 的魅力所在。
【免费下载链接】peerjsSimple peer-to-peer with WebRTC.项目地址: https://gitcode.com/gh_mirrors/pe/peerjs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考