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.

Quellinformationen

Repository
vitejs/devtools
Letzte Quellaktivität
7. Oktober 2026 um 06:12
Erkannte Sprache von SKILL.md
Englisch
Sterne
1.212
Forks
96

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
13 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
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'`) |
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen