Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions alias.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export const alias = {
'@vitejs/devtools-rpc/presets/ws/server': r('rpc/src/presets/ws/server.ts'),
'@vitejs/devtools-rpc/presets/ws/client': r('rpc/src/presets/ws/client.ts'),
'@vitejs/devtools-rpc/presets': r('rpc/src/presets/index.ts'),
'@vitejs/devtools-rpc/client': r('rpc/src/client.ts'),
'@vitejs/devtools-rpc/server': r('rpc/src/server.ts'),
'@vitejs/devtools-rpc': r('rpc/src'),
'@vitejs/devtools-kit/client': r('kit/src/client/index.ts'),
'@vitejs/devtools-kit/constants': r('kit/src/constants.ts'),
Expand Down
104 changes: 99 additions & 5 deletions docs/kit/rpc.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,12 @@ const plugin: Plugin = {

### Function Types

| Type | Description | Caching |
|------|-------------|---------|
| `query` | Fetch data, read operations | Can be cached |
| `action` | Side effects, mutations | Not cached |
| `static` | Constant data that never changes | Cached indefinitely |
| Type | Description | Caching | Dump Support |
|------|-------------|---------|--------------|
| `query` | Fetch data, read operations | Can be cached | ✓ (manual) |
| `static` | Constant data that never changes | Cached indefinitely | ✓ (automatic) |
| `action` | Side effects, mutations | Not cached | ✗ |
| `event` | Emit events, no response | Not cached | ✗ |

### Handler Arguments

Expand Down Expand Up @@ -104,6 +105,99 @@ setup: (ctx) => {
}
```

> [!IMPORTANT]
> For build mode compatibility, compute data in the setup function using the context rather than relying on runtime global state. This allows the dump feature to pre-compute results at build time.

### Dump Feature for Build Mode

When using `vite devtools build` to create a static DevTools build, the server cannot execute functions at runtime. The **dump feature** solves this by pre-computing RPC results at build time.

#### How It Works

1. At build time, `dumpFunctions()` executes your RPC handlers with predefined arguments
2. Results are stored in `.vdt-rpc-dump.json` in the build output
3. The static client reads from this JSON file instead of making live RPC calls

#### Static Functions (Recommended)

Functions with `type: 'static'` are **automatically dumped** with no arguments:

```ts
const getConfig = defineRpcFunction({
name: 'my-plugin:get-config',
type: 'static', // Auto-dumped with inputs: [[]]
setup: ctx => ({
handler: async () => ({
root: ctx.viteConfig.root,
plugins: ctx.viteConfig.plugins.map(p => p.name),
}),
}),
})
```

This works in both dev mode (live) and build mode (pre-computed).

#### Query Functions with Dumps

For `query` functions that need arguments, define `dump` in the setup:

```ts
const getModule = defineRpcFunction({
name: 'my-plugin:get-module',
type: 'query',
setup: (ctx) => {
// Collect all module IDs at build time
const moduleIds = Array.from(ctx.viteServer?.moduleGraph?.idToModuleMap.keys() || [])

return {
handler: async (id: string) => {
const module = ctx.viteServer?.moduleGraph?.getModuleById(id)
return module ? { id, size: module.transformResult?.code.length } : null
},
dump: {
inputs: moduleIds.map(id => [id]), // Pre-compute for all modules
fallback: null, // Return null for unknown modules
},
}
},
})
```

#### Recommendations for Plugin Authors

To ensure your DevTools work in build mode:

1. **Prefer `type: 'static'`** for functions that return constant data
2. **Return context-based data in setup** rather than accessing global state in handlers
3. **Define dumps in setup function** for query functions that need pre-computation
4. **Use fallback values** for graceful degradation when arguments don't match

```ts
// ✓ Good: Returns static data, works in build mode
const getPluginInfo = defineRpcFunction({
name: 'my-plugin:info',
type: 'static',
setup: ctx => ({
handler: async () => ({
version: '1.0.0',
root: ctx.viteConfig.root,
}),
}),
})

// ✗ Avoid: Depends on runtime server state
const getLiveMetrics = defineRpcFunction({
name: 'my-plugin:metrics',
type: 'query', // No dump - won't work in build mode
handler: async () => {
return getCurrentMetrics() // Requires live server
},
})
```

> [!TIP]
> If your data genuinely needs live server state, use `type: 'query'` without dumps. The function will work in dev mode but gracefully fail in build mode.

## Client-Side Calls

### In Iframe Pages
Expand Down
1 change: 0 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
"@vitejs/devtools-rolldown": "workspace:*",
"@vitejs/devtools-rpc": "workspace:*",
"birpc": "catalog:deps",
"birpc-x": "catalog:deps",
"cac": "catalog:deps",
"h3": "catalog:deps",
"immer": "catalog:deps",
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/node/host-functions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { DevToolsNodeContext, DevToolsNodeRpcSession, DevToolsRpcClientFunctions, DevToolsRpcServerFunctions, RpcBroadcastOptions, RpcFunctionsHost as RpcFunctionsHostType, RpcSharedStateHost } from '@vitejs/devtools-kit'
import type { BirpcGroup } from 'birpc'
import type { AsyncLocalStorage } from 'node:async_hooks'
import { RpcFunctionsCollectorBase } from 'birpc-x'
import { RpcFunctionsCollectorBase } from '@vitejs/devtools-rpc'
import { createDebug } from 'obug'
import { createRpcSharedStateServerHost } from './rpc-shared-state'

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/node/ws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import type { WebSocket } from 'ws'
import type { RpcFunctionsHost } from './host-functions'
import { AsyncLocalStorage } from 'node:async_hooks'
import process from 'node:process'
import { createRpcServer } from '@vitejs/devtools-rpc'
import { createWsRpcPreset } from '@vitejs/devtools-rpc/presets/ws/server'
import { createRpcServer } from '@vitejs/devtools-rpc/server'
import c from 'ansis'
import { getPort } from 'get-port-please'
import { createDebug } from 'obug'
Expand Down
1 change: 0 additions & 1 deletion packages/kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
"dependencies": {
"@vitejs/devtools-rpc": "workspace:*",
"birpc": "catalog:deps",
"birpc-x": "catalog:deps",
"immer": "catalog:deps"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/src/client/docks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { RpcFunctionsCollector } from 'birpc-x'
import type { RpcFunctionsCollector } from '@vitejs/devtools-rpc'
import type { Raw } from 'vue'
import type { DevToolsDockEntriesGrouped } from '../../../core/src/client/webcomponents/state/dock-settings'
import type { DevToolsDockEntry, DevToolsDocksUserSettings, DevToolsDockUserEntry, DevToolsRpcClientFunctions, EventEmitter } from '../types'
Expand Down
4 changes: 2 additions & 2 deletions packages/kit/src/client/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import type { WebSocketRpcClientOptions } from '@vitejs/devtools-rpc/presets/ws/
import type { BirpcOptions, BirpcReturn } from 'birpc'
import type { ConnectionMeta, DevToolsRpcClientFunctions, DevToolsRpcServerFunctions, EventEmitter, RpcSharedStateHost } from '../types'
import type { DevToolsClientContext, DevToolsClientRpcHost, RpcClientEvents } from './docks'
import { createRpcClient } from '@vitejs/devtools-rpc'
import { RpcFunctionsCollectorBase } from '@vitejs/devtools-rpc'
import { createRpcClient } from '@vitejs/devtools-rpc/client'
import { createWsRpcPreset } from '@vitejs/devtools-rpc/presets/ws/client'
import { RpcFunctionsCollectorBase } from 'birpc-x'
import { UAParser } from 'my-ua-parser'
import { createEventEmitter } from '../utils/events'
import { nanoid } from '../utils/nanoid'
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ export * from './views'
export * from './vite-augment'
export * from './vite-plugin'

export type { RpcDefinitionsFilter, RpcDefinitionsToFunctions } from 'birpc-x'
export type { RpcDefinitionsFilter, RpcDefinitionsToFunctions } from '@vitejs/devtools-rpc'
2 changes: 1 addition & 1 deletion packages/kit/src/types/rpc.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { RpcFunctionsCollectorBase } from '@vitejs/devtools-rpc'
import type { DevToolsNodeRpcSessionMeta } from '@vitejs/devtools-rpc/presets/ws/server'
import type { BirpcReturn } from 'birpc'
import type { RpcFunctionsCollectorBase } from 'birpc-x'
import type { SharedState } from '../utils/shared-state'
import type { DevToolsRpcClientFunctions, DevToolsRpcServerFunctions, DevToolsRpcSharedStates } from './rpc-augments'
import type { DevToolsNodeContext } from './vite-plugin'
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/src/utils/define.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { DevToolsNodeContext } from '../types'
import { createDefineWrapperWithContext } from 'birpc-x'
import { createDefineWrapperWithContext } from '@vitejs/devtools-rpc'

export const defineRpcFunction = createDefineWrapperWithContext<DevToolsNodeContext>()
Loading
Loading