呱呱聚合
← 返回基因库
图像与设计

调试 json-render 生成式 UI 时,挂载…

任何 json-render 应用需要调试生成式 UI、检查 spec 树、编辑运行时状态、查看动作时间线、跟踪流补丁、浏览 catalog 或拾取 DOM 对应 spec key 时使用。

被复用0 次
复用有效—
置信度55%
沉淀时间2026-09-23
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
来自 oscar.ren 的小呱沉淀
GDI C 38/100

进化评分(GDI)

综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」

内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15

适用场景

调试 json-render 生成式 U特定

解决思路

  1. 安装核心包和匹配宿主渲染器的适配器:React 用 `npm install @json-render/devtools @json-render/devtools-react`,Vue 用 `@json-render/devtools-vue`,Svelte 用 `@json-render/devtools-svelte`,Solid 用 `@json-render/devtools-solid`。
  2. 将 `<JsonRenderDevtools />` 放在已有 `<JSONUIProvider>`(或框架等价物)内部任意位置,无需其他接线。
  3. React 用法:从 `@json-render/devtools-react` 导入 `JsonRenderDevtools`,在 `<JSONUIProvider registry={registry} handlers={handlers}>` 内与 `<Renderer spec={spec} registry={registry} />` 并列渲染 `<JsonRenderDevtools spec={spec} catalog={catalog} messages={messages} />`。
  4. Vue 用法:`<script setup>` 从 `@json-render/devtools-vue` 导入,在 `<JSONUIProvider :registry={registry}>` 内渲染 `<Renderer :spec={spec} :registry={registry} />` 和 `<JsonRenderDevtools :spec={spec} :catalog={catalog} :messages={messages} />`。
  5. Svelte 用法:`<script>` 从 `@json-render/devtools-svelte` 导入,在 `<JSONUIProvider {registry}>` 内渲染 `<Renderer {spec} {registry} />` 和 `<JsonRenderDevtools {spec} {catalog} {messages} />`。
  6. Solid 用法:从 `@json-render/devtools-solid` 导入,在 `<JSONUIProvider registry={registry}>` 内渲染 `<Renderer spec={spec()} registry={registry} />` 和 `<JsonRenderDevtools spec={spec()} catalog={catalog} messages={messages()} />`。
  7. 使用悬浮开关:面板右下角出现浮动切换按钮。
  8. 使用热键:`Ctrl`/`Cmd` + `Shift` + `J`,可通过 `hotkey` prop 配置。
  9. 调整抽屉:抽屉可调整大小,高度持久化到 `localStorage`。
  10. 传 `spec` (`Spec | null`):当前 spec。
  11. 传 `catalog` (`Catalog | null`):目录定义;Catalog 面板必需。
  12. 传 `messages` (`UIMessage[]`):AI SDK `useChat` 消息;会扫描其中的 spec data parts。
  13. 传 `initialOpen` (`boolean`):启动时是否打开。
  14. 传 `position` (`bottom-right` | `bottom-left` | `right`):停靠位置和切换按钮角落;`bottom-*` 停靠底部;`right` 停靠右边缘全高(推荐给已使用 `100vh` 或固定底栏的 app-shell)。
  15. 传 `hotkey` (`string | false`):默认 `mod+shift+j`。
  16. 传 `bufferSize` (`number`):事件环形缓冲上限,默认 500。
  17. 传 `reserveSpace` (`boolean`,默认 `true`):为 true 时面板通过给 `body` 加 `padding-bottom` / `padding-right` 推挤宿主应用;设为 `false` 时面板为纯覆盖层。
  18. 传 `allowDockToggle` (`boolean`,默认 `true`):显示工具栏按钮,让用户在底部停靠和右侧停靠之间切换;选择持久化到 `localStorage`,并在后续挂载时覆盖 `position`;传 `false` 锁定到 `position`。
  19. 传 `onEvent` (`(DevtoolsEvent) => void`):可选事件监听。
  20. 使用 Spec 面板:查看以 `spec.root` 为根的元素树;查看 props/visibility/events/watchers 详情;集成 `validateSpec` 警告。
  21. 使用 State 面板:查看每个 JSON Pointer 路径,并用 `store.set` 内联编辑。
  22. 使用 Actions 面板:查看已派发动作时间线(name、params、result/error、duration)。
  23. 使用 Stream 面板:查看 spec patches、text chunks、token usage、lifecycle markers,并按 generation 分组。
  24. 使用 Catalog 面板:查看 catalog 中声明的 components + actions,并显示 prop chips。
  25. 使用拾取器:点击面板头部工具栏按钮(Chrome-DevTools 风格,不是标签页)激活 pick mode,然后点击页面中任一渲染元素;选中项会跳转到 Spec 标签并聚焦该元素;按 `Esc` 取消。
  26. 处理预留空间与停靠:面板可停靠底部或右边缘;默认用户可用工具栏按钮切换两者,选择持久化到 `localStorage`;如果宿主应用只兼容一种停靠,设 `allowDockToggle={false}` 隐藏按钮并将停靠锁定为 `position`。
  27. 选择初始停靠:底部停靠(默认)最适合 docs / marketing / content-flow 站点,以及用 `height: 100%` 链(`html { height: 100% }` → `body { height: 100% }` → `.app { height: 100% }`)构建的 app shell;面板把高度写入 `--jr-devtools-offset-bottom` 并给 `body` 加匹配的 `padding-bottom`,因此非 fixed 内容自然让出空间。
  28. 选择右边缘停靠:`position` 设为 `right` 推荐给使用 `100vh` 或 `position: fixed; bottom: 0` 的 app-shell 布局;右侧停靠避开底部边缘,并把宽度写入 `--jr-devtools-offset-right`。
  29. 对使用 `100vh`、`position: fixed` 或 `position: sticky` 的应用,用已发布的 CSS 自定义属性为特定元素手动留空间:`.composer { bottom: var(--jr-devtools-offset-bottom, 0); }`、`.sidebar { right: var(--jr-devtools-offset-right, 0); }`、`.app-shell { height: calc(100vh - var(--jr-devtools-offset-bottom, 0)); }`。
  30. 如果自动 body padding 对某布局有问题,传 `reserveSpace={false}` 让面板变纯覆盖层;CSS 自定义属性仍会发布,可手动预留空间。
  31. 记住 `--jr-devtools-offset` 是当前活动边缘的向后兼容别名。
  32. 一页多个 renderer 时:只放一个顶层 `<JSONUIProvider>`,让每个 renderer 共享一个 state store 和一个 action dispatcher;Devtools 放在该 provider 内即可看到全部内容。
  33. 一页多个 renderer 时:每个 renderer 使用各自的 spec,但共享 state;每条 assistant message 直接渲染 `<Renderer spec={msgSpec} registry={registry} />`,不要包自己的 `StateProvider`;不同 message 的 state path 不能冲突。
  34. 一页多个 renderer 时:按轮次给 state 加命名空间;当来源是 AI stream 时,给 agent 唯一 `messageId`,并要求每个元素 key(`<id>-root`)和 state path(`/<id>/count`)都带有该前缀。
  35. 一页多个 renderer 时:传 `spec={latest}` + `messages={all}`;`spec` 驱动 Spec 面板(通常是 newest assistant message 的 spec),`messages` 给 Stream 面板提供每一轮的 patches。
  36. 一页多个 renderer 时:Actions 和 picker 已经是全局的;`registerActionObserver` 捕获树中任何 `ActionProvider` 的派发,`data-jr-key` 由 renderer 自己写入,所以 Pick 能跨所有渲染元素工作,不论来自哪条 message。
  37. 参考 `examples/devtools` 查看按此方式接好的完整 AI chat。
  38. React 专用 imperative API:从 `@json-render/devtools-react` 导入 `useJsonRenderDevtools`,调用 `const devtools = useJsonRenderDevtools();`,然后 `devtools?.open();`、`devtools?.toggle();`、`devtools?.recordEvent({ kind: 'stream-text', at: Date.now(), text: 'hi' });`。
  39. Imperative API 在生产环境或组件挂载前返回 `null`。
  40. 服务端 stream tap:从 `@json-render/devtools` 导入 `tapJsonRenderStream`、`createEventStore`,从 `@json-render/core` 导入 `pipeJsonRender`。
  41. 服务端 stream tap:`const events = createEventStore({ bufferSize: 1000 }); const tapped = tapJsonRenderStream(result.toUIMessageStream(), events); writer.merge(pipeJsonRender(tapped));`。
  42. 服务端 stream tap:YAML 等价物是 `tapYamlStream`。
  43. 生产安全:组件在 `NODE_ENV === 'production'` 时渲染 `null`。
  44. 底层隔离:面板使用 Shadow-DOM 隔离,样式不会泄漏到宿主应用,反之亦然。
  45. 底层缓冲:使用环形缓冲事件存储,记录有上限的 devtools 事件(状态变化、动作派发、流补丁等)。
  46. 底层动作观察:每个框架的 `ActionProvider` 通过 `@json-render/core` 中的 `notifyActionDispatch` / `notifyActionSettle` 上报;devtools 通过 `registerActionObserver` 订阅。
  47. 底层拾取标记:devtools 挂载时,`ElementRenderer` 会把每个渲染元素包进 `<span data-jr-key='...' style='display:contents'>`,以便 picker 将 DOM 映射回 spec key,且无布局影响。

适用边界 · 注意事项