Skip to main content

writing-vite-devtools-integrations

Creates devtools integrations that mount inside the Vite DevTools hub via @vitejs/devtools-kit. Use when building Vite plugins with devtools panels, RPC functions, dock entries, shared state, messages/notifications, terminals, command palette entries, or any hub-level integration. Applies to files importing from @vitejs/devtools-kit or containing devtools.setup hooks in Vite plugins. For building one portable devtool integration without a hub (CLI, static deploy, MCP), see the `devframe` skill instead.

소스 정보

저장소
vitejs/devtools
최근 소스 활동
2026년 10월 7일 06:12
감지된 SKILL.md 언어
영어
스타
1,204
포크
92

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
13 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
writing-vite-devtools-integrations
description
Creates devtools integrations that mount inside the Vite DevTools hub via @vitejs/devtools-kit. Use when building Vite plugins with devtools panels, RPC functions, dock entries, shared state, messages/notifications, terminals, command palette entries, or any hub-level integration. Applies to files importing from @vitejs/devtools-kit or containing devtools.setup hooks in Vite plugins. For building one portable devtool integration without a hub (CLI, static deploy, MCP), see the `devframe` skill instead.
# Vite DevTools Kit **`@vitejs/devtools-kit` is the hub that unites many devtools integrations.** It owns the cross-tool surface — docking, the command palette, terminal aggregation, cross-tool toasts — and wraps the framework-neutral [Devframe](https://devfra.me/) container with the Vite-specific glue (`Plugin.devtools.setup`). If you have a portable Devframe app already, drop it in via `createPluginFromDevframe(d)` from `@vitejs/devtools-kit/node` and the kit auto-derives the iframe dock entry. If you're authoring a Vite-specific integration that needs hub features directly, reach for `Plugin.devtools.setup`. ## Core Concepts A DevTools plugin extends a Vite plugin with a `devtools.setup(ctx)` hook. The context is the **kit-augmented context** (`KitNodeContext` extended with Vite-specific fields) — it carries Devframe's portable surface plus the hub-only subsystems the kit owns: | Property | Layer | Purpose | |----------|-------|---------| | `ctx.docks` | **kit** | Register dock entries (iframe, action, custom-render, launcher, json-render) | | `ctx.terminals` | **kit** | Spawn and manage child processes with streaming terminal output | | `ctx.messages` | **kit** | Emit structured message entries and toast notifications | | `ctx.commands` | **kit** | Register executable commands with keyboard shortcuts and palette visibility | | `ctx.rpc` | devframe | Register RPC functions, broadcast to clients | | `ctx.rpc.sharedState` | devframe | Synchronized server-client state | | `ctx.rpc.streaming` | devframe | Streaming channels — chunk-style server↔client data with cancellation, replay, Web Streams interop | | `ctx.views` | devframe | Host static files for UI (`hostStatic(base, distDir)`) | | `ctx.diagnostics` | devframe | Structured diagnostics host (nostics) — register custom error codes | | `ctx.createJsonRenderer` | core | Create server-side JSON render specs for zero-client-code UIs | | `ctx.viteConfig` | core | Resolved Vite configuration | | `ctx.viteServer` | core | Dev server instance (dev mode only) | | `ctx.mode` | devframe | `'dev'` or `'build'` | ## Quick Start: Bridge a Devframe App If you already have a portable Devframe definition, this is the one-liner. The kit synthesises the iframe dock entry from the definition's `id` / `name` / `icon` / `basePath`, mounts the SPA via `views.hostStatic`, runs the devtool's own `setup`, then runs the optional kit-only `options.setup`. ```ts // vite.config.ts import { createPluginFromDevframe } from '@vitejs/devtools-kit/node' import devtool from './my-devtool' export default { plugins: [ createPluginFromDevframe(devtool, { // Optional kit-only setup for hub features: setup(ctx) { ctx.commands.register({ id: 'my-devtool:clear-cache', title: 'Clear Cache', handler: () => {/* ... */}, }) }, }), ], } ``` ## Quick Start: Minimal Hub-Native Plugin When the integration is intrinsically tied to Vite (it inspects the resolved config, augments middleware, etc.), reach for `Plugin.devtools.setup` directly: ```ts /// <reference types="@vitejs/devtools-kit" /> import type { Plugin } from 'vite' export default function myPlugin(): Plugin { return { name: 'my-plugin', devtools: { setup(ctx) { ctx.docks.register({ id: 'my-plugin', title: 'My Plugin', icon: 'ph:puzzle-piece-duotone', type: 'iframe', url: 'https://example.com/devtools', }) }, }, } } ``` ## Quick Start: Full Integration ```ts /// <reference types="@vitejs/devtools-kit" /> import type { Plugin } from 'vite' import { fileURLToPath } from 'node:url' import { defineRpcFunction } from '@vitejs/devtools-kit' export default function myAnalyzer(): Plugin { const data = new Map<string, { size: number }>() return { name: 'my-analyzer', // Collect data in Vite hooks transform(code, id) { data.set(id, { size: code.length }) }, devtools: { setup(ctx) { // 1. Host static UI const clientPath = fileURLToPath( new URL('../dist/client', import.meta.url) ) ctx.views.hostStatic('/__my-analyzer/', clientPath) // 2. Register dock entry ctx.docks.register({ id: 'my-analyzer', title: 'Analyzer', icon: 'ph:chart-bar-duotone', type: 'iframe', url: '/__my-analyzer/', }) // 3. Register RPC function ctx.rpc.register( defineRpcFunction({ name: 'my-analyzer:get-data', type: 'query', setup: () => ({ handler: async () => Array.from(data.entries()), }), }) ) }, }, } } ``` ## Namespacing Convention **CRITICAL**: Always prefix RPC functions, shared state keys, dock IDs, and command IDs with your plugin name: ```ts // Good - namespaced 'my-plugin:get-modules' 'my-plugin:state' 'my-plugin:clear-cache' // command ID // Bad - may conflict 'get-modules' 'state' ``` ## Dock Entry Types | Type | Use Case | |------|----------| | `iframe` | Full UI panels, dashboards (most common) | | `json-render` | Server-side JSON specs — zero client code needed | | `action` | Buttons that trigger client-side scripts (inspectors, toggles) | | `custom-render` | Direct DOM access in panel (framework mounting) | | `launcher` | Actionable setup cards for initialization tasks | ### Iframe Entry ```ts ctx.docks.register({ id: 'my-plugin', title: 'My Plugin', icon: 'ph:house-duotone', type: 'iframe', url: '/__my-plugin/', }) ``` Iframes can also point at a **remote-hosted URL** that connects back via WebSocket, so you don't have to ship a SPA dist with your plugin: ```ts ctx.docks.register({ id: 'my-remote-tool', title: 'My Tool', icon: 'ph:cloud-duotone', type: 'iframe', url: 'https://example.com/devtools', remote: true, // or { transport: 'query', originLock: false } }) ``` On the hosted page, call `connectRemoteDevTools()` from `@vitejs/devtools-kit/client` to get a fully connected `DevToolsRpcClient`. Dev-mode only — auto-hidden in build mode. See [Remote Client Patterns](./references/remote-client-patterns.md). ### Action Entry ```ts ctx.docks.register({ id: 'my-inspector', title: 'Inspector', icon: 'ph:cursor-duotone', type: 'action', action: { importFrom: 'my-plugin/devtools-action', importName: 'default', }, }) ``` ### Custom Render Entry ```ts ctx.docks.register({ id: 'my-custom', title: 'Custom View', icon: 'ph:code-duotone', type: 'custom-render', renderer: { importFrom: 'my-plugin/devtools-renderer', importName: 'default', }, }) ``` ### JSON Render Entry Build UIs entirely from server-side TypeScript — no client code needed: ```ts const ui = ctx.createJsonRenderer({ root: 'root', elements: { root: { type: 'Stack', props: { direction: 'vertical', gap: 12 }, children: ['heading', 'info'], }, heading: { type: 'Text', props: { content: 'Hello from JSON!', variant: 'heading' }, }, info: { type: 'KeyValueTable', props: { entries: [ { key: 'Version', value: '1.0.0' }, { key: 'Status', value: 'Running' }, ], }, }, }, }) ctx.docks.register({ id: 'my-panel', title: 'My Panel', icon: 'ph:chart-bar-duotone', type: 'json-render', ui, }) ``` ### Launcher Entry ```ts const entry = ctx.docks.register({ id: 'my-setup', title: 'My Setup', icon: 'ph:rocket-launch-duotone', type: 'launcher', launcher: { title: 'Initialize My Plugin', description: 'Run initial setup before using the plugin', buttonStart: 'Start Setup', buttonLoading: 'Setting up...', onLaunch: async () => { // Run initialization logic }, }, }) ``` ## Terminals & Subprocesses Spawn and manage child processes with streaming terminal output: ```ts const session = await ctx.terminals.startChildProcess( { command: 'vite', args: ['build', '--watch'], cwd: process.cwd(), }, { id: 'my-plugin:build-watcher', title: 'Build Watcher', icon: 'ph:terminal-duotone', }, ) // Lifecycle controls await session.terminate() await session.restart() ``` A common pattern is combining with launcher docks — see [Terminals Patterns](./references/terminals-patterns.md). ## Commands & Command Palette Register executable commands discoverable via `Mod+K` palette: ```ts import { defineCommand } from '@vitejs/devtools-kit' ctx.commands.register(defineCommand({ id: 'my-plugin:clear-cache', title: 'Clear Build Cache', icon: 'ph:trash-duotone', keybindings: [{ key: 'Mod+Shift+C' }], when: 'clientType == embedded', handler: async () => { /* ... */ }, })) ``` Commands support sub-commands (two-level hierarchy), conditional visibility via `when` clauses, and user-customizable keyboard shortcuts. See [Commands Patterns](./references/commands-patterns.md) and [When Clauses](./references/when-clauses.md) for full details. ## Logs & Notifications Plugins can emit structured log entries from both server and client contexts. Logs appear in the built-in **Logs** panel and can optionally show as toast notifications. ### Fire-and-Forget ```ts // No await needed context.messages.add({ message: 'Plugin initialized', level: 'info', }) ``` ### With Handle ```ts const handle = await context.messages.add({ id: 'my-build', message: 'Building...', level: 'info', status: 'loading', }) // Update later await handle.update({ message: 'Build complete', level: 'success', status: 'idle', }) // Or dismiss await handle.dismiss() ``` ### Key Fields | Field | Type | Description | |-------|------|-------------| | `message` | `string` | Short title (required) | | `level` | `'info' \| 'warn' \| 'error' \| 'success' \| 'debug'` | Severity (required) | | `description` | `string` | Detailed description | | `notify` | `boolean` | Show as toast notification | | `filePosition` | `{ file, line?, column? }` | Source file location (clickable) | | `elementPosition` | `{ selector?, boundingBox?, description? }` | DOM element position | | `id` | `string` | Explicit id for deduplication | | `status` | `'loading' \| 'idle'` | Shows spinner when loading | | `category` | `string` | Grouping (e.g., `'a11y'`, `'lint'`) |
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기