Chitchatter 嵌入集成使用指南

Chitchatter 嵌入集成实战:chat-room Web Component 全属性、postMessage 配置握手、iframe 直嵌,含 root-url 默认指向官方站点的踩坑实录,全部示例无头浏览器实测。

ChitchatterChitchatterWebRTC自托管2026/10/25

Chitchatter 嵌入集成使用指南

目标:把 Chitchatter(main 分支 commit b0114d5)聊天房间嵌入到自己的网页——<chat-room> Web Component 全属性详解、postMessage 配置握手原理、iframe 直接嵌入法,全部示例在真实部署上逐条验证(含「默认指向官方站点」的踩坑实录)。已在 Ubuntu 22.04 自托管实例 + Chromium 无头浏览器实测通过。

一、环境信息

本文所有命令与回显均在以下实测环境中执行:

  • 聊天服务端:自托管 Chitchatter(commit b0114d52eb786d240ef3a9d2b3691b215e29dbf0),构建产物由 Nginx 托管,本文示例地址 http://<聊天站点>/(实验中为本机 8142 端口映射)
  • 宿主页面:任意静态 HTML,本文示例经本地 HTTP 服务(http://<宿主站点>:8150/demo.html)提供
  • 验证浏览器:Chromium 无头模式(--headless --dump-dom)
  • SDK:构建产物中的 sdk.js(实测 3.14 kB)

💡 说明:嵌入的本质是「宿主页面加载一个 <script> + 写一个自定义标签」,SDK 内部再用 iframe 加载聊天站点并做配置握手。聊天逻辑、密钥协商、消息收发全部发生在聊天站点域名的 iframe 里,宿主页面拿不到消息内容。

二、前置条件

  1. 一个可访问的 Chitchatter 部署(官方公共实例 https://chitchatter.im/ 或自托管实例,部署方法见本专栏《Ubuntu 22.04 安装 Chitchatter 指南》或《Chitchatter Docker Compose 部署指南》篇);
  2. 一个你自己的 HTML 页面(能改 <head> 与 <body> 即可);
  3. 若嵌入后要用音视频/屏幕共享:宿主页面与聊天站点都必须是 HTTPS(或 localhost),否则浏览器拒绝授权(安全上下文限制)。

三、依赖引入

在宿主页面 <head> 中引入 sdk.js:

<script src="http://<聊天站点>/sdk.js"></script>

验证 SDK 可被第三方站点正常引用(响应头需含 Access-Control-Allow-Origin: *,自托管 Nginx 配置方法见《Chitchatter 配置参数详解》篇 5.3 节):

curl -sI http://<聊天站点>/sdk.js

实测回显:

HTTP/1.1 200 OK
Server: nginx/1.31.8
Content-Type: application/javascript
Content-Length: 3135
Access-Control-Allow-Origin: *
Cache-Control: no-cache

脚本加载完成后,浏览器即注册了 <chat-room> 自定义元素,无需任何框架,原生 HTML 即可使用。

四、核心 API 与配置

4.1 <chat-room> 属性一览

以下属性清单来自 SDK 源码(sdk/sdk.ts 与 src/models/sdk.ts 的 ChatEmbedAttributes 枚举),并在本文示例中逐项验证:

属性类型默认值说明
room字符串当前页面 URL房间名(URL 编码后拼到 public/<房间名>)。不设则同一篇页面共享同一房间
root-urlURL构建时的 VITE_HOMEPAGE(默认 https://chitchatter.im/)聊天站点根地址。自托管必须显式设置,原因见 4.3 踩坑实录
user-name字符串随机生成嵌入用户的显示昵称
user-id字符串随机生成嵌入用户的稳定 ID(同 ID 在房间中视为同一用户)
color-modelight / dark跟随用户设置嵌入房间的主题色
play-message-sound布尔(存在即真)不发声带此属性则收到消息播放提示音
width / height / styleiframe 标准属性—透传到内部 iframe
sandbox / referrerpolicyiframe 标准属性—透传到内部 iframe,可做安全收紧

4.2 配置握手原理(postMessage)

了解握手过程有助于排障。SDK 内部流程(源码实测逻辑):

  1. <chat-room> 插入页面后创建 shadow DOM,内嵌一个 iframe,地址为 <root-url>public/<room>?embed=&getSdkConfig=&parentDomain=<宿主源>;
  2. iframe 加载完成后,SDK 监听 message 事件,等待聊天页发来 configRequested;
  3. 收到后把 user-name、color-mode 等配置以 config 消息 postMessage 回给 iframe(超时 10 秒未握手会在宿主控制台报 [chitchatter-sdk] configuration was not sent successfully);
  4. 全过程校验来源 origin,跨站伪造配置会被丢弃。

iframe 的权限白名单固定为 camera;microphone;display-capture;fullscreen(源码 iframeFeatureAllowList.ts),保证嵌入房间内可发起音视频通话与屏幕共享。

4.3 踩坑实录:自托管时 root-url 必须显式指定

sdk.js 的默认根地址在构建时固化,且构建脚本强制取 package.json 的 homepage 字段(https://chitchatter.im/),命令行环境变量覆盖不了(详见《Chitchatter 配置参数详解》篇 5.1.3)。实测:用自托管实例的 sdk.js、不写 root-url,嵌入的 iframe 实际指向了官方站点——

诊断页实测输出(无头浏览器 dump-dom 摘录):

{"customElementDefined":true,"shadowRoot":true,"iframeSrc":"https://chitchatter.im/public/quzuo-e1-demo?embed=&getSdkConfig=&parentDomain=http%253A%252F%252F127.0.0.1%253A8150","iframeAllow":"camera;microphone;display-capture;fullscreen"}

加上 root-url 属性后重新实测:

{"customElementDefined":true,"shadowRoot":true,"iframeSrc":"http://localhost:8142/public/quzuo-e1-demo?embed=&getSdkConfig=&parentDomain=http%253A%252F%252F127.0.0.1%253A8150","iframeAllow":"camera;microphone;display-capture;fullscreen"}

可见 iframeSrc 已正确指向自托管实例,且自动携带了 embed、getSdkConfig、parentDomain 三个握手参数。如果不想每个嵌入点都写 root-url,就在构建前把 package.json 的 homepage 改成自己的站点根地址再 npm run build。

五、集成示例

5.1 Web Component 嵌入(推荐)

完整的可独立运行示例(保存为 demo.html,经任意静态 HTTP 服务提供,把两个地址换成你的实际站点):

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8" />
  <title>Chitchatter 嵌入演示</title>
  <script src="http://<聊天站点>/sdk.js"></script>
  <style>
    body { font-family: sans-serif; margin: 2rem }
    chat-room { display: block; height: 480px; border: 1px solid #ccc; border-radius: 8px; overflow: hidden }
  </style>
</head>
<body>
  <h1>站内嵌入 Chitchatter 房间</h1>
  <chat-room root-url="http://<聊天站点>/" room="quzuo-e1-demo"
             user-name="演示用户" color-mode="light" play-message-sound="false"></chat-room>
</body>
</html>

实测验证:无头浏览器加载该页面后,<chat-room> 内部成功创建 iframe 并指向 http://<聊天站点>/public/quzuo-e1-demo?embed=&getSdkConfig=&parentDomain=...(回显见 4.3),房间页 React 应用正常挂载:

/snap/bin/chromium --headless --disable-gpu --virtual-time-budget=10000 --dump-dom \
  "http://localhost:8142/public/quzuo-e1-demo?embed=&getSdkConfig=&parentDomain=http%3A%2F%2F127.0.0.1%3A8150" | head -c 300

(localhost:8142 即本文实验的聊天站点地址;换成你的实际站点即可。)

实测回显(节选,可见 MUI 组件树已渲染):

...id="root"><div class="MuiBox-root css-158t3i"><span class="MuiCircularProgress-root...

(首屏的加载圈是在连接公共 tracker 找同伴,属正常过程;两名用户打开同一房间名即互见。)

5.2 iframe 直接嵌入(无 SDK 方式)

不需要配置握手(昵称随机、无主题指定)时,可跳过 SDK 直接 iframe 房间页:

<iframe src="http://<聊天站点>/public/quzuo-e1-iframe"
        width="100%" height="480"
        style="border:1px solid #ccc;border-radius:8px"
        allow="camera;microphone;display-capture;fullscreen"></iframe>

⚠️ 注意:iframe 直接嵌入务必自己加 allow 属性(SDK 方式自动设置,裸 iframe 不加则无法音视频通话)。两种方式可同页并存,本文实验页面即同时嵌了一个 <chat-room> 和一个裸 iframe,互不干扰。

5.3 动态房间分配(每页面一房间)

room 缺省时取当前页面 URL 作房间名——即「同一篇文章/同一个商品页的访客自动进入同一房间」。直接写 <chat-room root-url="..."></chat-room> 即可实现评论式旁路聊天,无需为每个页面生成房间名。

六、注意事项

  1. HTTPS 与安全上下文:嵌入页或聊天站点任一为非 HTTPS(非 localhost),浏览器将禁止摄像头/麦克风授权;生产环境两端都应 HTTPS。
  2. 许可证传导:Chitchatter 为 GPL-2.0-or-later。页面嵌入 sdk.js 属于与 GPL 作品的组合分发,商用闭源产品嵌入前需评估 GPL 义务(嵌入官方公共实例 chitchatter.im 的 sdk.js 同样如此)。
  3. 消息不落地:嵌入房间与正常房间一样消息瞬态,宿主页面无法读取/留存聊天内容(shadow DOM + 跨域 iframe 隔离),不要把嵌入当作「客服聊天记录」方案。
  4. 房间名即凭证:room 属性值会出现在 iframe URL 中,不要用敏感信息作房间名;需要准入控制时用私密房间思路——把 room 设为高熵随机串且不在页面源码中明文出现(例如由后端按会话动态渲染)。
  5. 握手失败排查:宿主控制台出现 configuration was not sent successfully 时,按序检查 root-url 是否指向可访问的聊天站点、sdk.js 是否 200、浏览器控制台是否有混合内容/CSP 拦截。
  6. 第三方 Cookie/存储:聊天页用 localStorage 保存界面设置,浏览器禁用第三方 Cookie 的严格模式下嵌入实例每次载入都是全新设置,属预期行为。

七、参考链接

本专栏其他篇目:《Chitchatter 介绍与选型指南》《Ubuntu 22.04 安装 Chitchatter 指南》《Chitchatter Docker Compose 部署指南》《Chitchatter 配置参数详解》。