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
آخر نشاط في المصدر
٧ أكتوبر ٢٠٢٦ في ٠٦:١٢
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
١٬٢٠٣
التفرعات
٩٢

خيارات التثبيت

يُحدَّد 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