mcpField
D
devtools

devtools

github.com/vercel-labs开发18.8k8.3k 次安装5 天前更新
代码仓库

关于 devtools

@json-render/devtools 为 json-render 应用提供悬浮式检查面板,面向使用 React、Vue、Svelte 或 Solid 的开发者。它集中查看规范、状态、动作、流事件和目录,并支持元素拾取与面板停靠。

主要功能

  1. 01检查元素树及验证警告
  2. 02查看和编辑 JSON Pointer 状态
  3. 03追踪动作调用及结果
  4. 04查看规范流补丁和事件
  5. 05拾取页面元素并定位规范

适用场景

  1. 01调试 AI 生成的界面
  2. 02检查状态绑定和动作调用
  3. 03跟踪多轮流式生成
  4. 04在不同框架应用中检查渲染器

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/vercel-labs/json-render --skill devtools

安装后在 Claude Code 中输入/devtools确认已加载。

详细介绍

@json-render/devtools

适用于 json-render 应用的浮动检查器面板。与框架无关的核心,以及针对各框架的适配器(React、Vue、Svelte、Solid)。

对生产环境安全:当 process.env.NODE_ENV === "production" 时,组件不会渲染 devtools UI,包括打包工具在浏览器中替换该表达式但不存在全局 process 的情况。未打包且没有 process.env 的环境会保留开发行为。

安装

安装核心包,以及与宿主应用渲染器相匹配的适配器。

# React
npm install @json-render/devtools @json-render/devtools-react

# Vue
npm install @json-render/devtools @json-render/devtools-vue

# Svelte
npm install @json-render/devtools @json-render/devtools-svelte

# Solid
npm install @json-render/devtools @json-render/devtools-solid

即插即用

将 <JsonRenderDevtools /> 放在现有 <JSONUIProvider>(或对应框架的等效组件)内的任意位置。无需进行其他配置。

React
import { JsonRenderDevtools } from "@json-render/devtools-react";

<JSONUIProvider registry={registry} handlers={handlers}>
  <Renderer spec={spec} registry={registry} />
  <JsonRenderDevtools spec={spec} catalog={catalog} messages={messages} />
</JSONUIProvider>;
Vue
<script setup>
import { JsonRenderDevtools } from "@json-render/devtools-vue";
</script>

<template>
  <JSONUIProvider :registry="registry">
    <Renderer :spec="spec" :registry="registry" />
    <JsonRenderDevtools :spec="spec" :catalog="catalog" :messages="messages" />
  </JSONUIProvider>
</template>
Svelte
<script>
  import { JsonRenderDevtools } from "@json-render/devtools-svelte";
</script>

<JSONUIProvider {registry}>
  <Renderer {spec} {registry} />
  <JsonRenderDevtools {spec} {catalog} {messages} />
</JSONUIProvider>
Solid
import { JsonRenderDevtools } from "@json-render/devtools-solid";

<JSONUIProvider registry={registry}>
  <Renderer spec={spec()} registry={registry} />
  <JsonRenderDevtools
    spec={spec()}
    catalog={catalog}
    messages={messages()}
  />
</JSONUIProvider>;

控件

  • 浮动切换按钮显示在右下角。
  • 快捷键:Ctrl/Cmd + Shift + J(可通过 hotkey prop 配置)。
  • 抽屉大小可调整;高度会保存到 localStorage。

Props

  • spec (Spec | null) — 当前 spec。
  • catalog (Catalog | null) — catalog 定义;Catalog 面板必需。
  • messages (UIMessage[]) — AI SDK useChat 消息;会扫描其中的 spec 数据部分。
  • initialOpen (boolean) — 初始时打开。
  • position ("bottom-right" | "bottom-left" | "right") — 停靠位置和切换按钮所在角落。"bottom-*" 停靠在底部;"right" 停靠在右侧边缘并占满高度(推荐用于已使用 100vh 或固定底栏的应用外壳)。
  • hotkey (string | false) — 默认为 "mod+shift+j"。
  • bufferSize (number) — 事件环形缓冲区上限,默认为 500。
  • reserveSpace (boolean,默认为 true) — 为 true 时,面板会通过在 body 上应用 padding-bottom / padding-right 来推动宿主应用。设为 false 可使面板保持纯叠加层。
  • allowDockToggle (boolean,默认为 true) — 显示工具栏按钮,让用户在底部停靠和右侧停靠之间切换面板。用户的选择会保存到 localStorage,并在后续挂载时覆盖 position。传入 false 可将停靠位置锁定为 position。
  • onEvent ((DevtoolsEvent) => void) — 可选的事件回调。

面板

  • Spec — 以 spec.root 为根的元素树;显示 props/可见性/事件/监听器详情;集成 validateSpec 警告。
  • State — 所有 JSON Pointer 路径;可通过 store.set 直接编辑。
  • Actions — 已分发操作的时间线(名称、参数、结果/错误、耗时)。
  • Stream — 按生成过程分组显示 spec 补丁、文本块、令牌用量和生命周期标记。
  • Catalog — catalog 中声明的组件和操作,并显示属性标签。

选择器(工具栏)

元素选择器是面板标题栏中的工具栏按钮(类似 Chrome DevTools),不是选项卡。点击按钮启用选择模式,然后点击页面中任意已渲染的元素,即可跳转到 Spec 选项卡并聚焦该元素。按 Esc 取消。

预留空间与停靠

面板可以停靠在底部或右侧边缘。默认情况下,用户可以通过工具栏按钮在两种位置间切换(选择会保存到 localStorage)。如果宿主应用只支持一种停靠位置,请设置 allowDockToggle={false}——按钮会隐藏,停靠位置会锁定为 position。

选择适合布局的初始停靠位置:

  • 底部停靠(默认) — 最适合文档、营销和内容流网站,以及采用 height: 100% 链的应用外壳(html { height: 100% } → body { height: 100% } → .app { height: 100% })。面板会将其高度写入 --jr-devtools-offset-bottom,并为 body 应用对应的 padding-bottom,因此非固定内容会自然腾出空间。
  • 右侧停靠(position="right")— 推荐用于采用 100vh 或 position: fixed; bottom: 0 的应用外壳布局。右侧停靠完全避开底部边缘,并将其宽度写入 --jr-devtools-offset-right。

采用 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)); }

如果自动添加到 body 的内边距导致特定布局出现问题,请传入 reserveSpace={false},让面板仅作为覆盖层显示——CSS 自定义属性仍会发布,因此你仍可手动预留空间。

(--jr-devtools-offset 会作为兼容旧版本的别名,指向当前启用的边缘。)

单页上的多个渲染器(例如聊天)

单个 <JsonRenderDevtools /> 可以同时检查多个 <Renderer /> 实例——例如,每条助手消息都渲染自己的规范的聊天,或由多个独立组件构成的仪表板。具体做法:

  1. 使用一个顶层 <JSONUIProvider>,让每个渲染器共享同一个状态存储和操作分发器。Devtools 位于此 Provider 内部,可通过它查看所有内容。
  2. 每个渲染器使用各自的规范,共享状态 — 每条助手消息都直接渲染 <Renderer spec={msgSpec} registry={registry} />,而不是用自己的 StateProvider 包裹。不同消息的状态路径不得冲突。
  3. 按轮次为状态添加命名空间 — 如果数据源是 AI 流,请为 Agent 提供唯一的 messageId,并要求每个元素键(<id>-root)和状态路径(/<id>/count)都以此为前缀。
  4. 传入 spec={latest} + messages={all} — spec 驱动 Spec 面板(通常是最新助手消息的规范),而 messages 则为 Stream 面板提供每一轮的补丁。
  5. 操作和选择器已经是全局的 — registerActionObserver 会捕获树中任何 ActionProvider 的分发操作,渲染器自身会写入 data-jr-key,因此 Pick 可作用于每个已渲染元素,无论它由哪条消息生成。

请参阅 examples/devtools,了解按此方式接入的完整 AI 聊天示例。

命令式 API(仅限 React)

import { useJsonRenderDevtools } from "@json-render/devtools-react";

const devtools = useJsonRenderDevtools();
devtools?.open();
devtools?.toggle();
devtools?.recordEvent({ kind: "stream-text", at: Date.now(), text: "hi" });

在生产环境中或组件挂载前会返回 null。

服务端流拦截器

在 API 路由处捕获规范补丁,以便事件在服务端持久保存,或流入你自己的遥测系统。

import { tapJsonRenderStream, createEventStore } from "@json-render/devtools";
import { pipeJsonRender } from "@json-render/core";

const events = createEventStore({ bufferSize: 1000 });
const tapped = tapJsonRenderStream(result.toUIMessageStream(), events);
writer.merge(pipeJsonRender(tapped));

YAML 等效项:tapYamlStream。

实现原理

  • 通过 Shadow DOM 隔离的面板 — 面板样式不会泄漏到宿主应用,反之亦然。
  • 环形缓冲事件存储 — 对 devtools 事件日志(状态变更、操作分发、流补丁等)设有容量上限。
  • 操作观察器注册表 — 每个框架的 ActionProvider 都会通过 @json-render/core 中的 notifyActionDispatch / notifyActionSettle 报告;devtools 则通过 registerActionObserver 订阅。
  • 为选择器标记元素 — devtools 挂载期间,ElementRenderer 会将每个已渲染元素包在 <span data-jr-key="..." style="display:contents"> 中,以便选择器将 DOM 映射到规范键。不会影响布局。

评论

支持 Markdown