Devframe 发布:一次定义,随处运行的通用 DevTools 生态
译注:本文翻译自 Anthony Fu 博客文章《Pluggable, Extensible, and Playful DevTools》,原文发布于 2026 年 9 月 16 日,并与 Devframe 官方文档交叉发布。原文链接见文末。
多年来,作者构建了相当多的 DevTools:UnoCSS Inspector、Vite Plugin Inspect、Vitest UI、Nuxt DevTools、ESLint Config Inspector、Node Modules Inspector 等。它们看起来各不相同,但本质上都在做同一件事:让隐式状态变得可见。与其猜测某个 CSS 工具类为何生成、某个模块如何被转换、某个文件适用哪份配置,不如直接看到过程并与之交互。
尽管用途不同,这些工具共享大量基础设施:客户端-服务器通信、状态同步、序列化、静态资源托管、Web 界面。每个工具还要决定如何打包、分发、挂载到服务器并连接宿主。实践中,每个工具都在孤立地重建许多相同的部件。
生态中也在重复同样的模式。框架和构建工具各自构建 DevTools,能力常常重叠——数据检查器、资源查看器、构建分析器、终端、编辑器集成。但大多数都绑定在特定框架及其开发服务器细节上(如何提供资源、处理请求、升级连接)。结果是相似功能被分别重建、分别改进。
如果能把 DevTools 从这些边界中解放出来会怎样? 如果每项能力都可复用、可模块化,就能惠及所有受支持的宿主。与其把同一想法分散到多个版本,社区可以合力打磨一个工具,把它做得更好。
从愿景到 Devframe
这是作者自 2023 年起分享的「通用 DevTools 生态」愿景。方向是对的,但找到能使其成立的边界要难得多。当工作从 Nuxt DevTools 转向 Vite DevTools,作者加入 Vercel 后终于有机会在更大范围探索。Vite 提供了验证体验的具体落点,但目标始终是开放给其他构建工具链。随着 LLM 让设计探索与验证大大加速,正确的边界逐渐浮现。
Devframe 是一个框架中立的基座:一次定义 DevTool,然后把它带到不同宿主、独立界面和智能体(Agent)中。可以把它类比为构建 DevTools 的框架,就像 Nuxt 或 Next.js 是构建 Web 应用的框架。在集成层,它的角色类似 unplugin:unplugin 为插件提供跨打包器的通用接口,Devframe 则为 DevTools 提供跨宿主的通用定义。
一次定义,一个标准处理器,多个适配器
每个 Devframe 都从 defineDevframe() 开始,把工具的身份与它提供的能力关联起来:
// my-tool.ts
import { defineDevframe } from 'devframe'
import { inspectProject } from './rpc'
export default defineDevframe({
id: 'my-tool',
name: 'My Tool',
setup(ctx) {
ctx.scope('my-tool').rpc.register(inspectProject)
},
})定义与呈现方式无关。initDevframe() 把它变成活实例:
// server.ts
import { initDevframe } from 'devframe/initiate'
import myDevframe from './my-tool'
const myTool = initDevframe(myDevframe, {
base: '/__my-tool/',
})
myTool.handler // Web Standard Request -> Response
myTool.nodeMiddleware // Connect 风格中间件处理器成为工具的边界。在其背后,Devframe 在同一命名空间下提供 Web 界面、连接元数据、实时 RPC、鉴权以及可选的 MCP 端点。工具不再绑定特定开发服务器 API,宿主只需理解 Web 标准的 Request 和 Response。
这一「处理器优先」模型深受 Comark Content 启发。现代框架、运行时和构建工具已围绕这一边界收敛:Hono 和 Nitro 直接使用 Web 标准请求,Next.js 和 SvelteKit 暴露路由处理器,Vite 和 Rsbuild 接受 Connect 风格中间件——同一个实例通过 nodeMiddleware 提供。
// server.ts
import { Hono } from 'hono'
import { devtools } from './devtools'
const app = new Hono()
app.all(devtools.base + '*', c =>
devtools.handler(c.req.raw),
)这就是可移植性的几乎全部诀窍。任何支持 Web 标准处理器或 Connect 风格中间件的框架或构建工具,都能挂载同一个 Devframe,接入同一生态。
适配器只是便利层
处理器是最小公分母。对于常见入口,更高层的适配器把它打包成熟悉的形式。同一定义可以变成独立 CLI、专用开发服务器、Vite DevTools 插件、MCP 服务器或静态报告:
import { createPluginFromDevframe } from '@vitejs/devtools-kit/node'
import { createBuild } from 'devframe/adapters/build'
import { createCac } from 'devframe/adapters/cac'
import { createDevServer } from 'devframe/adapters/dev'
import { createMcpServer } from 'devframe/adapters/mcp'
import myDevframe from './my-tool'
export const runCli = () => createCac(myDevframe).parse()
export const startServer = () => createDevServer(myDevframe)
export const vitePlugin = createPluginFromDevframe(myDevframe)
export const startMcp = () => createMcpServer(myDevframe, { transport: 'stdio' })
export const buildReport = () => createBuild(myDevframe, { outDir: 'dist-static' })一个包可以同时提供多个入口。例如构建检查器可以提供独立 CLI、在 CI 中生成静态报告、作为 Vite DevTools 中的停靠面板出现,并允许智能体查询当前构建——全部由同一定义支撑。Node Modules Inspector、ESLint Config Inspector 和 Vite Plugin Inspect 已在采用这一模型。前端也由各工具自行决定,Devframe 只处理协议与运行时。为验证这一点,内置插件横跨 Vue、Svelte、Solid、React 和 Next.js。
可视化与智能体双界面
随着智能体成为开发工作流的一部分,DevTool 不再只是给人看的面板,也应向智能体和其他工具提供结构化的内部状态与能力接口。两种界面各有所长而非互相替代:可视化适合探索、概览和比较;智能体可以获取聚焦上下文、与代码库关联并执行多步操作。呈现方式不同,但事实来源一致。
在 Devframe 中,RPC 函数默认私有,必须显式暴露给智能体。MCP 适配器把这些函数、可读资源和选定的共享状态转换为智能体可消费的界面。描述、schema 和安全元数据帮助智能体理解每项能力应在何时、如何被使用。
Devframe 还集成了 Vercel 的 json-render,允许用受限组件目录中的可序列化数据描述 UI,便于智能体生成仪表盘和交互工具,同时保持输出可预测。同一机制也支持服务端提供 UI:Devframe 发布视图及其状态,宿主提供渲染器。借助预置参考 UI,工具无需编写或构建自定义客户端即可起步。协议保持渲染器无关,每个宿主可用自己的框架、组件和设计系统渲染同一视图。
内置插件
抽象只有在真实工具能运行其上时才有说服力。官方插件刻意使用不同前端框架构建,每个都可独立运行或挂载到受支持的宿主。
- Data Inspector(Vue):为服务端实时对象提供交互式工作台。工具可注册对象为数据源,并在拥有它的进程内用 Jora 查询。独立运行时可以检查 JSON/JSONL 文件、生成自包含报告或附加到运行中的 Node.js 进程。可试用:
pnpx @devframes/plugin-data-inspector - Terminals(Svelte):基于浏览器的终端面板,支持只读进程输出和交互式 PTY 会话。可独立运行:
pnpx @devframes/plugin-terminals,直接在浏览器中打开交互式终端,可用于管理进程、运行命令,甚至运行 Claude Code 这类智能体。 - Accessibility Inspector(Solid):用 axe-core 扫描宿主应用,列出 WCAG 违规并高亮对应元素,还能把发现转化为给智能体的修复提示。灵感来自 @nuxt/a11y,抽取为 Devframe 插件后能力不再局限于 Nuxt。
其他官方插件还覆盖 Web 版 VS Code 编辑器、资源管理、Git 面板、Open Graph 预览,以及 Devframe 自身的 RPC 与状态检查器。它们共享的是 Devframe 定义与协议,而非前端技术栈。
从单个 Devframe 到 DevTools 宿主
当多个 Devframe 同时活跃,发现问题随之而来:用户如何找到并在它们之间切换?许多 DevTools 把自己的 URL 打印到控制台,或向宿主应用注入浮动按钮。工具越多,控制台越像 URL 目录,页面也堆满互不相关的按钮,而每个 DevTool 还得自行构建发现机制。
为此 Devframe 提供组合层 Hub。@devframes/hub 是无头且框架中立的,多个 Devframe 可注册其中,贡献停靠面板、命令、消息、终端和共享状态。对用户而言,它们通过一个一致入口呈现;对工具而言,Hub 提供可互相发现与协作的共享上下文。
import { initHub } from '@devframes/hub/initiate'
import { createTerminalsDevframe } from '@devframes/plugin-terminals'
const hub = initHub({
base: '/__devframes/',
devframes: [
createTerminalsDevframe(),
// ...
],
ui: await import('@devframes/hub-ui').then(m => m.createUi()),
})
hub.handler
hub.nodeMiddleware挂载的 Devframe 共享一个 RPC 注册表、状态存储、连接、鉴权门和可选的聚合 MCP 端点。Hub 本身保持无头:@devframes/hub-ui 提供参考界面,产品也可自带 UI 而不改动底层工具。仓库包含 Vite、Next.js、Hono、Nitro 和 Rsbuild 的可运行参考宿主。
旗舰宿主:Vite DevTools 与 Nuxt DevTools
Vite DevTools 是首个基于该基座构建的旗舰宿主,提供面向 Vite 的界面与集成,同时用 initHub() 做组合与服务。除 Vite 与 Rolldown 分析、Vitest UI、Oxc 工具链外,它给独立 DevTools 一个共同协作的场所。Devframe 可通过适配器加入,普通 Vite 插件也能通过新的 devtools.setup 入口直接贡献:
// vite.config.ts
import { createPluginFromDevframe } from '@vitejs/devtools-kit/node'
import { createMyDevframe } from 'my-devframe-tool'
import { defineConfig } from 'vite'
const myDevframe = createMyDevframe()
export default defineConfig({
devtools: true,
plugins: [
createPluginFromDevframe(myDevframe),
{
name: 'vite-plugin-my-tool',
devtools: {
setup(ctx) {
// 带 Vite 特定增强的 Devframe 上下文
},
},
},
],
})Nuxt DevTools v4 同时构建于两者之上:继承 Vite DevTools 与 Vue DevTools,再加入 Nuxt 特有知识——页面、模块、自动导入、服务端 API、运行时状态,以及来自 Nuxt 模块生态的贡献。Vue DevTools 也正在迁移到 Vite DevTools 基座,组件与响应式检查等 Vue 能力将能与 Vite 集成和通用 Devframe 在同一宿主中共存。
某种程度上,故事回到了起点:始于 Nuxt DevTools 的愿望,如今以可组合、可扩展、可跨宿主的形态回归。