WebSocket子协议是客户端与服务端协商应用层语义的机制,用于标识API版本并实现多版本路由与向前兼容;应使用语义化命名如"v2.chat.example.com",前端按兼容性降序声明,服务端匹配首个支持的协议并绑定对应处理器,连接生命周期内协议不可变更。

WebSocket子协议(Subprotocol)不是版本号标签,而是客户端与服务端之间协商应用层语义的机制。它本身不执行版本逻辑,但可作为轻量、标准、无侵入的“协议握手标识”,为多版本API提供清晰的路由依据和向前兼容基础。
子协议名即版本标识
子协议字符串应直接体现API语义版本,例如:
- "v2.chat.example.com" —— 明确指向第二版聊天协议
- "api-1.5+json" —— 表示兼容1.5及以上、以JSON为载体的API
- "legacy-v1" —— 专用于兜底老客户端,不带新字段或行为
避免使用模糊命名如"chat"或"myapp",否则无法区分行为差异;也不建议在子协议中嵌入动态值(如时间戳、用户ID),它只用于静态协商。
客户端按优先级声明候选协议
前端应按兼容性从高到低排列子协议数组,让服务端有明确选择依据:
立即学习“前端免费学习笔记(深入)”;
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 新版页面传
["v3.api.example.com", "v2.api.example.com", "legacy-v1"] - 旧版App仍可传
["legacy-v1"]或["v2.api.example.com"],保持连接成功
服务端收到后,从左到右匹配首个支持的协议并返回——这天然形成“降级链”。若只支持v2,则忽略v3请求,选v2;若v2已下线,就回落到legacy-v1。
服务端严格校验并路由到对应处理器
子协议协商成功后(ws.protocol非空),服务端必须将该连接绑定到对应版本的业务逻辑模块:
- 收到
ws.protocol === "v3.api.example.com"→ 走 v3 路由器,启用新字段校验、新事件类型、新序列化规则 - 收到
ws.protocol === "legacy-v1"→ 走兼容通道,屏蔽v2/v3新增字段,返回扁平结构响应
关键点:同一连接生命周期内,协议不可变更;所有消息处理、错误码定义、心跳格式都需与子协议声明一致。浏览器不干预语义,全靠服务端自律执行。
前端根据协商结果适配UI与行为
连接建立后,立即读取 ws.protocol 决定本页能力边界:
- 若为
"v3.api.example.com",启用拖拽排序、富文本消息预览等新功能 - 若协商结果是
"v2.api.example.com",隐藏v3专属控件,但保留v2全部交互 - 若
ws.protocol为空,说明协商失败——此时不应报错中断,而应回退到HTTP轮询或提示“请升级浏览器”
注意:DOM渲染、状态管理、本地缓存策略都应与协议版本对齐,避免“协议是v2,UI却按v3渲染导致字段undefined”这类不一致问题。


















