Skip to content

Commit d17da04

Browse files
committed
Add loro-protocol blog
1 parent 6de6ed5 commit d17da04

2 files changed

Lines changed: 126 additions & 0 deletions

File tree

pages/blog/_meta.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
export default {
2+
"loro-protocol": {
3+
theme: {
4+
toc: true,
5+
pagination: false,
6+
},
7+
},
28
"loro-mirror": {
39
theme: {
410
toc: true,

pages/blog/loro-protocol.mdx

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
title: "Loro 协议"
2+
date: 2025/10/30
3+
description: "Loro 协议在一条 WebSocket 连接上复用 CRDT 同步工作负载,并提供开源的 loro-websocket、loro-adaptors,以及使用相同协议的 Rust 客户端和服务端实现。"
4+
image: "/images/blog-loro-protocol.png"
5+
6+
---
7+
8+
## Loro 协议
9+
10+
import Authors, { Author } from "../../components/authors";
11+
12+
<Authors date="2025-10-30">
13+
<Author name="Zixuan Chen" link="https://www.loro.dev/" />
14+
</Authors>
15+
16+
![](/images/blog-loro-protocol.png)
17+
18+
开源的 Loro 协议项目包含 `loro-websocket` 包、`loro-adaptors` 中的适配器套件,以及能够在同一线路格式上互操作的 Rust 客户端与服务端实现。
19+
20+
[**Loro 协议**](https://github.com/loro-dev/protocol) 是一个为实时 CRDT 同步设计的协议。可以在[这里](https://github.com/loro-dev/protocol/blob/main/protocol.md)详细了解其设计。
21+
22+
它能够在单条 WebSocket 连接上高效运行多个相互独立的“房间”。
23+
24+
这使你可以在一条连接上同步应用状态,例如 Loro 文档、临时光标位置以及端到端加密的文档。它也兼容 Yjs。
25+
26+
### 快速开始:服务器与客户端示例
27+
28+
该协议由 `loro-websocket` 客户端和用于测试的最小化 `SimpleServer` 实现。你可以使用 `loro-adaptors` 将这些组件与 CRDT 状态桥接起来。
29+
30+
**服务器**
31+
32+
在开发环境中,你可以在 Node.js 中运行来自 `loro-websocket``SimpleServer`
33+
34+
```tsx
35+
// server.ts
36+
import { SimpleServer } from "loro-websocket/server";
37+
38+
const server = new SimpleServer({
39+
port: 8787,
40+
// SimpleServer 接受用于身份验证和数据持久化的钩子:
41+
// authenticate: async (roomId, crdt, auth) => { ... },
42+
// onLoadDocument: async (roomId, crdt) => { ... },
43+
// onSaveDocument: async (roomId, crdt, data) => { ... },
44+
});
45+
46+
server.start().then(() => {
47+
console.log("SimpleServer listening on ws://localhost:8787");
48+
});
49+
```
50+
51+
**客户端**
52+
53+
在客户端侧,你只需连接一次,然后通过不同的适配器加入多个房间。
54+
55+
```tsx
56+
// client.ts
57+
import { LoroWebsocketClient } from "loro-websocket";
58+
import { LoroAdaptor, LoroEphemeralAdaptor } from "loro-adaptors";
59+
60+
// 1. 创建并连接客户端
61+
const client = new LoroWebsocketClient({ url: "ws://localhost:8787" });
62+
await client.waitConnected();
63+
console.log("Client connected!");
64+
65+
// --- 房间 1:一个 Loro 文档 (%LOR) ---
66+
const docAdaptor = new LoroAdaptor();
67+
const docRoom = await client.join({
68+
roomId: "doc:123",
69+
crdtAdaptor: docAdaptor,
70+
});
71+
72+
// 本地编辑现在会自动同步
73+
const text = docAdaptor.getDoc().getText("content");
74+
text.insert(0, "Hello, Loro!");
75+
docAdaptor.getDoc().commit();
76+
77+
// --- 房间 2:同一套接字上的临时 Presence (%EPH) ---
78+
const ephAdaptor = new LoroEphemeralAdaptor();
79+
const presenceRoom = await client.join({
80+
roomId: "doc:123", // 可以使用相同的 roomId,但 magic bytes 不同
81+
crdtAdaptor: ephAdaptor,
82+
});
83+
84+
// 临时状态会同步,但服务器不会持久化它
85+
ephAdaptor.getStore().set("cursor", { x: 100, y: 100 });
86+
```
87+
88+
---
89+
90+
### 功能
91+
92+
#### 复用
93+
94+
每条二进制消息都以前四个 magic bytes 标识数据类型,随后附带 `roomId`。这一结构让服务器可以将消息路由到正确的处理器。一个客户端可以加入:
95+
96+
- `%LOR` (Loro Document)
97+
- `%EPH` (Loro 临时存储,用于光标和在线状态)
98+
- `%ELO` (端到端加密的 Loro 文档)
99+
- `%YJS``%YAW` (用于 Yjs 文档和 Awareness 的互操作)
100+
101+
所有流量都在同一套接字上运行。
102+
103+
#### 兼容性
104+
105+
Loro 协议旨在适配 Cloudflare 等运行环境:
106+
107+
- 分片:大型更新会自动拆分为不超过 256 KiB 的片段,并由接收方重新组装,从而应对对 WebSocket 消息大小有限制的平台。
108+
- 应用层 keepalive:协议定义了简单的 `"ping"``"pong"` 文本帧。它们绕过二进制封装,让客户端在浏览器或无服务器环境中检查连接存活性,此时传输层的 TCP keepalive 通常不可用。
109+
110+
该仓库还提供与 TypeScript 包对应的 Rust 客户端和服务端。
111+
112+
#### 实验性的端到端加密
113+
114+
端到端加密的 Loro 已包含在 `loro-protocol` 中,但该功能目前仍处于实验阶段:线路格式和密钥管理 API 仍可能变化,暂不适合用于已经过生产级安全审计的场景。在客户端与 `EloLoroAdaptor` 搭配时,服务器会在不解密的情况下转发加密记录。
115+
116+
### 当前状态与许可
117+
118+
Loro 协议已经基本稳定。我们欢迎社区反馈和贡献,尤其是当前设计难以满足的用例。
119+
120+
https://github.com/loro-dev/protocol 中的所有包均以宽松的 MIT 许可证开源发布。

0 commit comments

Comments
 (0)