Skip to content

Commit bd22d46

Browse files
committed
docs: update kit docs
1 parent 589a393 commit bd22d46

6 files changed

Lines changed: 488 additions & 447 deletions

File tree

docs/.vitepress/config.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,16 @@ export default defineConfig({
1717
// https://vitepress.dev/reference/default-theme-config
1818
nav: [
1919
{ text: 'Guide', link: '/guide/' },
20-
{ text: 'DevTools Kit', link: '/kit/' },
20+
{
21+
text: 'DevTools Kit',
22+
items: [
23+
{ text: 'Introduction', link: '/kit/' },
24+
{ text: 'DevTools Plugin', link: '/kit/devtools-plugin' },
25+
{ text: 'Dock System', link: '/kit/dock-system' },
26+
{ text: 'RPC', link: '/kit/rpc' },
27+
{ text: 'Shared State', link: '/kit/shared-state' },
28+
],
29+
},
2130
{
2231
text: `v${version}`,
2332
items: [
@@ -39,6 +48,10 @@ export default defineConfig({
3948
text: 'DevTools Kit',
4049
items: [
4150
{ text: 'Introduction', link: '/kit/' },
51+
{ text: 'DevTools Plugin', link: '/kit/devtools-plugin' },
52+
{ text: 'Dock System', link: '/kit/dock-system' },
53+
{ text: 'RPC', link: '/kit/rpc' },
54+
{ text: 'Shared State', link: '/kit/shared-state' },
4255
],
4356
},
4457
],

docs/kit/devtools-plugin.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
outline: deep
3+
---
4+
5+
# DevTools Plugin
6+
7+
A DevTools plugin is a **superset** of a Vite plugin—meaning any Vite plugin can become a DevTools plugin by simply adding a `devtools` hook. This allows you to extend the DevTools infrastructure with custom data visualizations, actions, and integrations.
8+
9+
## Installation
10+
11+
To get started, install the `@vitejs/devtools-kit` package in your Vite plugin project. It's typically fine to add it as a dev dependency since we only need it for types on the Node.js side.
12+
13+
```zsh
14+
pnpm install -D @vitejs/devtools-kit
15+
```
16+
17+
Then referencing it in your plugin code, it will augment the `Plugin` interface with the `devtools` property.
18+
19+
Inside `devtools.setup`, you will get tools to register custom data visualization, actions, and more. See the sections below for details on [registering dock entries](./dock-system), and [RPC functions](./rpc).
20+
21+
```ts {1,9-14}
22+
/// <reference types="@vitejs/devtools-kit" />
23+
import { Plugin } from 'vite'
24+
25+
export default function myPlugin(): Plugin {
26+
return {
27+
name: 'my-plugin',
28+
// Do other plugin stuff...
29+
transform(code, id) {},
30+
// Devtools setup
31+
devtools: {
32+
setup(ctx) {
33+
console.log('My plugin setup')
34+
},
35+
},
36+
}
37+
}
38+
```
39+
40+
When users run their app with Vite DevTools enabled (`vite dev --ui`), your devtools setup function will be called.
41+
42+
## DevTools Context
43+
44+
The `setup` function receives a `DevToolsNodeContext` which provides access to:
45+
46+
- `ctx.docks`: Manage [dock entries](./dock-system)
47+
- `ctx.views`: Host static views
48+
- `ctx.rpc`: Register [RPC functions](./rpc) or broadcast to clients
49+
- `ctx.utils`: Utility functions
50+
- `ctx.viteConfig`: Vite configuration
51+
- `ctx.viteServer`: Vite dev server (in dev mode)
52+
- `ctx.mode`: Current mode (`'dev'` or `'build'`)
53+
54+
## Next Steps
55+
56+
- Learn how to [register dock entries](./dock-system) to create UI panels, actions, or custom renderers
57+
- Set up [RPC functions](./rpc) for server-client communication
58+
- Use [shared state](./shared-state) to synchronize data between server and client

docs/kit/dock-system.md

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
---
2+
outline: deep
3+
---
4+
5+
# Dock System
6+
7+
Dock entries are the primary way for users to interact with your DevTools integration. They appear as clickable items in the DevTools dock (similar to macOS Dock), and when activated, they can display:
8+
- An iframe panel with your custom UI
9+
- A custom-rendered panel directly in the user's app
10+
- An action button that triggers client-side scripts
11+
12+
The dock can be presented as a floating panel inside the user's app, a sidebar in browser extension mode, or in standalone mode. "Dock" refers to macOS's Dock, where you switch between different applications by clicking on them.
13+
14+
## Register A Dock Entry
15+
16+
To register a dock entry, you can use the `ctx.docks.register` method to add a new dock entry. The easiest approach is to register a iframe-based dock entry. Here we use VueUse's docs as an example:
17+
18+
```ts {6-12}
19+
export default function VueUseDevToolsDocs(): Plugin {
20+
return {
21+
name: 'vueuse:devtools:docs',
22+
devtools: {
23+
setup(ctx) {
24+
ctx.docks.register({
25+
id: 'vueuse:docs',
26+
title: 'VueUse',
27+
icon: 'https://vueuse.org/favicon.svg',
28+
type: 'iframe',
29+
url: 'https://vueuse.org',
30+
})
31+
},
32+
}
33+
}
34+
}
35+
```
36+
37+
The more practical usage is to build a local webpage to draw your own views and handle interactions. This allows you to use any frontend framework (Vue, React, Svelte, etc.) to build your DevTools UI.
38+
39+
For example, if you host a local custom view at `/.my-app`, you can register it as a dock entry like this:
40+
41+
```ts {6}
42+
ctx.docks.register({
43+
id: 'my-app',
44+
title: 'My App',
45+
icon: 'https://my-app.com/logo.svg',
46+
type: 'iframe',
47+
url: '/.my-app',
48+
})
49+
```
50+
51+
DevTools can also handle the page hosting for you. If you have your built SPA page under `./dist/client`, you can register it as a dock entry like this:
52+
53+
```ts {2}
54+
const pathClientDist = fileURLToPath(new URL('../dist/client', import.meta.url))
55+
ctx.views.hostStatic('/.my-app', pathClientDist)
56+
ctx.docks.register({
57+
id: 'my-app',
58+
title: 'My App',
59+
icon: 'https://my-app.com/logo.svg',
60+
type: 'iframe',
61+
url: '/.my-app',
62+
})
63+
```
64+
65+
This way DevTools will handle the dev server middleware to host the static files for you, and also copy the static files to the dist directory when in production build.
66+
67+
## Register An Action
68+
69+
Instead of an iframe panel, sometimes you might want to register an action button that triggers client-side scripts. This is useful when you want to:
70+
- Enable temporary inspector tools (e.g., DOM inspector, component inspector)
71+
- Toggle features in the user's app
72+
- Trigger one-time actions without showing a UI panel
73+
74+
For example, you might want to enable a temporary inspector tool to inspect the DOM of the client app and have the button appear in the DevTools dock.
75+
76+
```ts {6}
77+
ctx.docks.register({
78+
id: 'dom-inspector',
79+
title: 'DOM Inspector',
80+
type: 'action',
81+
action: {
82+
importFrom: 'vite-plugin-my-inspector/vite-devtools-action',
83+
importName: 'default',
84+
},
85+
icon: 'ph:cursor-duotone',
86+
})
87+
```
88+
89+
In your package, export the sub entrypoint for the action. The action script runs in the user's app context, giving you access to the app's DOM, state, and APIs.
90+
91+
```ts [src/vite-devtools-action.ts]
92+
import type { DevToolsClientScriptContext } from '@vitejs/devtools-kit/client'
93+
94+
export default function setupDevToolsAction(ctx: DevToolsClientScriptContext) {
95+
// Setup action will only execute when the entry is activated the first time
96+
97+
// Register listeners to handle events from the dock system
98+
ctx.current.events.on('entry:activated', () => {
99+
// Your action logic here
100+
console.log('DOM inspector started!')
101+
102+
// Example: Enable DOM inspection
103+
document.body.style.cursor = 'crosshair'
104+
105+
// You can also communicate with the server using [RPC](./rpc)
106+
})
107+
108+
ctx.current.events.on('entry:deactivated', () => {
109+
// Cleanup when the entry is deactivated
110+
document.body.style.cursor = ''
111+
})
112+
}
113+
```
114+
115+
And in your package.json, you can export the sub entrypoint:
116+
117+
```json [package.json]
118+
{
119+
"name": "vite-plugin-my-inspector",
120+
"exports": {
121+
"./vite-devtools-action": "./dist/vite-devtools-action.mjs"
122+
}
123+
}
124+
```
125+
126+
That's it! When users install your plugin, they can click your action button in the dock. When activated for the first time, the action script will be loaded and executed in the user's app context, allowing you to interact with their application directly.
127+
128+
## Register Custom Renderer
129+
130+
If you want to render your own views directly in the user's app instead of using an iframe, you can register a dock entry with a custom renderer. This gives you full control over the DOM and allows you to use any framework or vanilla JavaScript to build your UI.
131+
132+
```ts {6}
133+
ctx.docks.register({
134+
id: 'my-custom-view',
135+
title: 'My Custom View',
136+
type: 'custom-render',
137+
renderer: {
138+
importFrom: 'vite-plugin-my-inspector/vite-devtools-renderer',
139+
importName: 'default',
140+
},
141+
icon: 'ph:file-duotone'
142+
})
143+
```
144+
145+
Similar to [Action](#register-an-action), we write the renderer logic in a client script that we export as a sub export. The renderer gives you a DOM element (`panel`) that you can mount your UI to:
146+
147+
```ts [src/vite-devtools-renderer.ts]
148+
import type { DevToolsClientScriptContext } from '@vitejs/devtools-kit/client'
149+
150+
export default function setupDevToolsCustomRenderer(ctx: DevToolsClientScriptContext) {
151+
// Setup will only execute when the entry is activated the first time
152+
153+
// The 'dom:panel:mounted' event is called once when the panel DOM is ready
154+
// The DOM will be preserved when switching between dock entries
155+
ctx.current.events.on('dom:panel:mounted', (panel) => {
156+
// Render your custom DOM and mount to `panel`
157+
// You can use vanilla JavaScript or any framework you prefer
158+
const el = document.createElement('div')
159+
el.style.padding = '16px'
160+
el.innerHTML = '<h2>Hello from custom render dock!</h2>'
161+
162+
const btn = document.createElement('button')
163+
btn.textContent = 'Click me'
164+
btn.onclick = async () => {
165+
// You can communicate with the server using [RPC](./rpc)
166+
// const rpc = ctx.current.rpc
167+
// const data = await rpc.call('my-plugin:get-data', 'some-id')
168+
console.log('Button clicked!')
169+
}
170+
el.appendChild(btn)
171+
panel.appendChild(el)
172+
173+
// You can also use frameworks like Vue, React, etc.
174+
// import { createApp } from 'vue'
175+
// createApp(MyComponent).mount(panel)
176+
})
177+
178+
// Cleanup when the entry is deactivated (optional)
179+
ctx.current.events.on('entry:deactivated', () => {
180+
// Cleanup logic if needed
181+
})
182+
}
183+
```
184+
185+
**Note**: The panel DOM is preserved when users switch between dock entries, so you only need to set up your UI once in the `dom:panel:mounted` event. If you need to update the UI based on server state, use [RPC calls](./rpc#call-server-functions-from-client) to fetch fresh data.

0 commit comments

Comments
 (0)