Skip to content

feat: upgrade vite-plugin-inspect to v12, use devtools-kit RPC#966

Open
antfu wants to merge 2 commits intomainfrom
antfu/inspect-devtools-kit
Open

feat: upgrade vite-plugin-inspect to v12, use devtools-kit RPC#966
antfu wants to merge 2 commits intomainfrom
antfu/inspect-devtools-kit

Conversation

@antfu
Copy link
Member

@antfu antfu commented Mar 25, 2026

Summary

  • Upgrade vite-plugin-inspect from v11 to v12.0.0-beta.1 (now powered by @vitejs/devtools-kit)
  • Bump @vitejs/devtools-kit and @vitejs/devtools to ^0.1.11
  • Refactor getComponentsRelationships to use rpcHost.invokeLocal() instead of the removed plugin.api interface
  • Expose rpcHost on NuxtDevtoolsServerContext so integrations can call RPC functions registered by other plugins
  • Remove custom tab registration for Inspect (v12 registers its own dock entry via devtools-kit)

Test plan

  • Run playground and verify the Inspect tab appears in Vite DevTools
  • Verify the components graph loads correctly (exercises getComponentsRelationships)
  • Verify graceful fallback (warning + empty array) when inspect RPC is not yet registered

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@antfu antfu changed the title refactor: upgrade vite-plugin-inspect to v12, use devtools-kit RPC feat: upgrade vite-plugin-inspect to v12, use devtools-kit RPC Mar 25, 2026
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Mar 25, 2026

Deploying nuxt-devtools with  Cloudflare Pages  Cloudflare Pages

Latest commit: 4f1d67d
Status: ✅  Deploy successful!
Preview URL: https://a2b599ac.nuxt-devtools.pages.dev
Branch Preview URL: https://antfu-inspect-devtools-kit.nuxt-devtools.pages.dev

View logs

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 25, 2026

📝 Walkthrough

Walkthrough

The PR adds an optional devtoolsKit: DevToolsNodeContext | undefined field to NuxtDevtoolsServerContext and reroutes server RPC plumbing to use a stored DevToolsNodeContext (devtoolsKitCtx) instead of the previous RpcFunctionsHost/rpcHost. setupRPC now exposes a devtoolsKit getter and a connectDevToolsKit(ctx) connector. The vite-inspect integration was rewritten to use devtoolsKit.rpc.invokeLocal/has for metadata/module RPCs (with a runtime guard) and no longer relies on Nuxt lifecycle hooks or the ViteInspectAPI. Dependency ranges for devtools-related packages were bumped.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main changes: upgrading vite-plugin-inspect to v12 and refactoring to use devtools-kit RPC instead of the old plugin.api interface.
Description check ✅ Passed The description is directly related to the changeset, providing a clear summary of the upgrade objectives, implementation changes, and test plan for verifying the new RPC integration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch antfu/inspect-devtools-kit

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/devtools/src/server-rpc/index.ts (1)

105-109: ⚠️ Potential issue | 🔴 Critical

The getter is materialized to undefined and lost before integrations see it.

When setupRPC() returns { connectRpcHost, ...ctx } and then enableModule() rest-destructures the result with const { connectRpcHost: _connectRpcHost, ...ctx } = setupRPC(...), both spread and rest operations materialize the get rpcHost() accessor to its current value (which is undefined). The vite-inspect integration then receives ctx with a stale undefined property instead of a live accessor. Later, when connectRpcHost?.() updates rpcHost, the integration never observes the change, causing the graph RPC to keep falling back even after the host connects.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/devtools/src/server-rpc/index.ts` around lines 105 - 109, The getter
rpcHost on NuxtDevtoolsServerContext is being materialized to undefined when
setupRPC()'s return value is rest/spread-destructured in enableModule (const {
connectRpcHost: _connectRpcHost, ...ctx } = setupRPC(...)), which loses the live
accessor; fix by preserving the accessor instead of spreading: have enableModule
assign the whole setupRPC() result to a variable (e.g. const rpcCtx =
setupRPC(...)), extract only connectRpcHost by property access (const {
connectRpcHost } = rpcCtx) or rename it, and pass rpcCtx (or re-export the exact
object) so the get rpcHost() accessor remains a live getter; alternatively
ensure setupRPC returns an object where rpcHost is defined via
Object.defineProperty as a getter on the returned object so rest/spread does not
materialize it.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/devtools-kit/src/_types/server-ctx.ts`:
- Line 1: The public type NuxtDevtoolsServerContext currently re-exports the
third-party RpcFunctionsHost; remove the import of RpcFunctionsHost and instead
declare a local structural type (e.g. RpcFunctionsHostLike = Record<string, any>
or a minimal interface) and use that for the rpcHost property in
NuxtDevtoolsServerContext, so the published d.ts doesn’t reference
`@vitejs/devtools-kit`; alternatively (if you prefer the real type) add
"@vitejs/devtools-kit" to packages/devtools-kit/package.json dependencies—choose
one approach and update the NuxtDevtoolsServerContext rpcHost type accordingly.

In `@packages/devtools/src/integrations/vite-inspect.ts`:
- Around line 13-26: The handler closes over a stale rpcHost because setup()
destructures rpcHost from its parameter; stop destructuring rpcHost and instead
read the live RPC host from the full context inside
getComponentsRelationships(). Change the setup signature to accept the full
NuxtDevtoolsServerContext (or keep the current ctx param), remove rpcHost from
the parameter list, and replace rpcHost?.has(...) and rpcHost.invokeLocal(...)
calls in getComponentsRelationships() with ctx.rpcHost?.has(...) and
ctx.rpcHost.invokeLocal(...). Also ensure any type annotations are updated and
that this behavior aligns with the connectRpcHost flow so the handler uses the
updated ctx.rpcHost at runtime.

In `@pnpm-workspace.yaml`:
- Line 133: Replace the beta dependency version with the stable release: update
the vite-plugin-inspect entry from "vite-plugin-inspect: ^12.0.0-beta.1" to
"vite-plugin-inspect: 11.3.3" in pnpm-workspace.yaml (ensure you remove the
caret and beta tag), then run dependency install to lock the stable version and
rerun tests that exercise plugin integration (RPC interfaces like
meta.instances, get-metadata, get-modules-list) to confirm no regressions.

---

Outside diff comments:
In `@packages/devtools/src/server-rpc/index.ts`:
- Around line 105-109: The getter rpcHost on NuxtDevtoolsServerContext is being
materialized to undefined when setupRPC()'s return value is
rest/spread-destructured in enableModule (const { connectRpcHost:
_connectRpcHost, ...ctx } = setupRPC(...)), which loses the live accessor; fix
by preserving the accessor instead of spreading: have enableModule assign the
whole setupRPC() result to a variable (e.g. const rpcCtx = setupRPC(...)),
extract only connectRpcHost by property access (const { connectRpcHost } =
rpcCtx) or rename it, and pass rpcCtx (or re-export the exact object) so the get
rpcHost() accessor remains a live getter; alternatively ensure setupRPC returns
an object where rpcHost is defined via Object.defineProperty as a getter on the
returned object so rest/spread does not materialize it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6bcfbf88-f4a8-4255-bd89-730881bdb396

📥 Commits

Reviewing files that changed from the base of the PR and between 836ee1c and 15ae466.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (4)
  • packages/devtools-kit/src/_types/server-ctx.ts
  • packages/devtools/src/integrations/vite-inspect.ts
  • packages/devtools/src/server-rpc/index.ts
  • pnpm-workspace.yaml

@@ -1,3 +1,4 @@
import type { RpcFunctionsHost } from '@vitejs/devtools-kit'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Public export chain:"
sed -n '1,40p' packages/devtools-kit/src/types.ts
sed -n '1,80p' packages/devtools-kit/src/_types/index.ts

echo
echo "New external type reference:"
sed -n '1,120p' packages/devtools-kit/src/_types/server-ctx.ts | rg -n "@vitejs/devtools-kit|RpcFunctionsHost|rpcHost" || true

echo
echo "Declared dependency status:"
python <<'PY'
import json, pathlib
pkg = json.loads(pathlib.Path('packages/devtools-kit/package.json').read_text())
for section in ('dependencies', 'peerDependencies', 'devDependencies'):
    print(f"{section}: {pkg.get(section, {}).get('@vitejs/devtools-kit')}")
PY

Repository: nuxt/devtools

Length of output: 706


Avoid exporting an undeclared third-party type from @nuxt/devtools-kit.

NuxtDevtoolsServerContext is part of the public ./types surface, so the RpcFunctionsHost reference will flow into the published declaration files. TypeScript's publishing guide recommends putting declaration dependencies in dependencies so consumers don't have to install them manually, but packages/devtools-kit/package.json does not declare @vitejs/devtools-kit. Either add that package to the manifest or keep rpcHost structurally/local typed so the public d.ts does not import it. (typescriptlang.org)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/devtools-kit/src/_types/server-ctx.ts` at line 1, The public type
NuxtDevtoolsServerContext currently re-exports the third-party RpcFunctionsHost;
remove the import of RpcFunctionsHost and instead declare a local structural
type (e.g. RpcFunctionsHostLike = Record<string, any> or a minimal interface)
and use that for the rpcHost property in NuxtDevtoolsServerContext, so the
published d.ts doesn’t reference `@vitejs/devtools-kit`; alternatively (if you
prefer the real type) add "@vitejs/devtools-kit" to
packages/devtools-kit/package.json dependencies—choose one approach and update
the NuxtDevtoolsServerContext rpcHost type accordingly.

tinyexec: ^1.0.4
tinyglobby: ^0.2.15
vite-plugin-inspect: ^11.3.3
vite-plugin-inspect: ^12.0.0-beta.1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check vite-plugin-inspect v12 beta releases and changelog
npm view vite-plugin-inspect@12.0.0-beta.1 version

# Check available v12 versions to see if a stable release exists
npm view vite-plugin-inspect versions --json | jq '.[] | select(startswith("12."))'

# Look for changelog or breaking changes documentation
fd -t f -e md "CHANGELOG|BREAKING|MIGRATION" node_modules/vite-plugin-inspect 2>/dev/null || echo "Install dependencies first to check local changelog"

Repository: nuxt/devtools

Length of output: 138


🌐 Web query:

vite-plugin-inspect v12 changelog breaking changes

💡 Result:

No v12 version of vite-plugin-inspect exists as of 2026-03-25. The latest release is v11.3.3 (2025-08-25). The most recent breaking change was in v11.0.0: Drop CJS build, now ESM-only.

Citations:


🌐 Web query:

vite-plugin-inspect latest stable version

💡 Result:

The latest stable version of vite-plugin-inspect is 11.3.3.

Citations:


🌐 Web query:

@vitejs/devtools-kit 0.1.11 RPC interface compatibility

💡 Result:

No specific information found on @vitejs/devtools-kit version 0.1.11 or its RPC interface compatibility. The latest documented version appears to be around 0.1.2-0.1.3 (published March 2026), with the GitHub repo at v0.1.2 as of 2026-03-16. The RPC interface is described in official docs as a built-in type-safe bidirectional communication layer using defineRpcFunction, ctx.rpc.register, with types 'query', 'action', 'event', supporting schema validation via Valibot, shared state, and type extensions via module declaration merging. It depends on @vitejs/devtools-rpc and birpc ^4.0.0. The API is experimental and may change in any version. No breaking changes or compatibility issues specifically for 0.1.11 or RPC were identified in available sources. Check the GitHub repo https://github.com/vitejs/devtools (packages/kit) for latest releases and changelog.

Citations:


Use stable vite-plugin-inspect v11.3.3 instead of v12.0.0-beta.1.

The upgrade to v12.0.0-beta.1 uses a beta/pre-release version that is not recommended for production. The latest stable release is v11.3.3. Beta versions can contain bugs, incomplete features, and may have breaking changes not yet documented.

If v12 features are necessary, this change requires:

  • Thorough testing of the RPC interface and data structures (meta.instances, get-metadata, get-modules-list)
  • Verification that no breaking changes affect the plugin integration
  • Wait for a stable v12 release or document the specific features requiring the beta version
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pnpm-workspace.yaml` at line 133, Replace the beta dependency version with
the stable release: update the vite-plugin-inspect entry from
"vite-plugin-inspect: ^12.0.0-beta.1" to "vite-plugin-inspect: 11.3.3" in
pnpm-workspace.yaml (ensure you remove the caret and beta tag), then run
dependency install to lock the stable version and rerun tests that exercise
plugin integration (RPC interfaces like meta.instances, get-metadata,
get-modules-list) to confirm no regressions.

…sHost

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
packages/devtools/src/integrations/vite-inspect.ts (1)

13-26: ⚠️ Potential issue | 🔴 Critical

Don't capture devtoolsKit in setup()'s parameter list.

Even if the caller preserves the live getter, Line 13 still snapshots devtoolsKit before the connector runs, and getComponentsRelationships() then closes over that stale value. Lines 18-26 will keep returning the fallback empty array instead of recovering once inspect RPC is registered.

Suggested fix
-export async function setup({ rpc, devtoolsKit }: NuxtDevtoolsServerContext) {
+export async function setup(ctx: NuxtDevtoolsServerContext) {
+  const { rpc } = ctx
   const plugin = await createVitePluginInspect()
   addVitePlugin(plugin)

   async function getComponentsRelationships() {
+    const devtoolsKit = ctx.devtoolsKit
     if (!devtoolsKit?.rpc.has('vite-plugin-inspect:get-metadata')) {
       logger.warn('[nuxt-devtools] vite-plugin-inspect RPC functions not registered, component relationships unavailable')
       return []
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/devtools/src/integrations/vite-inspect.ts` around lines 13 - 26, The
getComponentsRelationships function is closing over the destructured devtoolsKit
from setup's parameter, causing a stale snapshot; change the setup signature to
accept the whole context object (e.g., setup(ctx: NuxtDevtoolsServerContext) or
setup(context)) instead of destructuring devtoolsKit, and update calls inside
(use ctx.rpc and ctx.devtoolsKit) so getComponentsRelationships reads
ctx.devtoolsKit at call time (not a captured variable), ensuring it sees the
updated RPC registration.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/devtools/src/module-main.ts`:
- Around line 132-137: The object rest (`...ctx`) from setupRPC is materializing
the devtoolsKit getter into a plain property, causing integrations that receive
ctx to see a stale/undefined devtoolsKit; instead, keep the original object
returned by setupRPC so the live getter is preserved: call const fullCtx =
setupRPC(nuxt, options), set connectDevToolsKit = fullCtx.connectDevToolsKit (or
extract _connectDevToolsKit from fullCtx), and pass fullCtx (not the spread ctx)
into integrations and other consumers so devtoolsKit remains a live accessor;
reference setupRPC, connectDevToolsKit/_connectDevToolsKit, devtoolsKit, and ctx
in the change.

---

Duplicate comments:
In `@packages/devtools/src/integrations/vite-inspect.ts`:
- Around line 13-26: The getComponentsRelationships function is closing over the
destructured devtoolsKit from setup's parameter, causing a stale snapshot;
change the setup signature to accept the whole context object (e.g., setup(ctx:
NuxtDevtoolsServerContext) or setup(context)) instead of destructuring
devtoolsKit, and update calls inside (use ctx.rpc and ctx.devtoolsKit) so
getComponentsRelationships reads ctx.devtoolsKit at call time (not a captured
variable), ensuring it sees the updated RPC registration.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 09d93759-eff4-464e-9cd8-721953d0756a

📥 Commits

Reviewing files that changed from the base of the PR and between 15ae466 and 4f1d67d.

📒 Files selected for processing (4)
  • packages/devtools-kit/src/_types/server-ctx.ts
  • packages/devtools/src/integrations/vite-inspect.ts
  • packages/devtools/src/module-main.ts
  • packages/devtools/src/server-rpc/index.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/devtools-kit/src/_types/server-ctx.ts
  • packages/devtools/src/server-rpc/index.ts

Comment on lines 132 to +137
const {
connectRpcHost: _connectRpcHost,
connectDevToolsKit: _connectDevToolsKit,
...ctx
} = setupRPC(nuxt, options)

connectRpcHost = _connectRpcHost
connectDevToolsKit = _connectDevToolsKit
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

find . -name "module-main.ts" -path "*/devtools/src/*" | head -5

Repository: nuxt/devtools

Length of output: 95


🏁 Script executed:

find . -name "*.ts" -path "*/devtools/*" | grep -E "(rpc|setup)" | head -10

Repository: nuxt/devtools

Length of output: 528


🏁 Script executed:

# Look at the module-main.ts file around lines 132-137
cat -n packages/devtools/src/module-main.ts | sed -n '120,150p'

Repository: nuxt/devtools

Length of output: 1055


🏁 Script executed:

# Find where setupRPC is defined
rg "export.*setupRPC|function setupRPC|const setupRPC" --type ts

Repository: nuxt/devtools

Length of output: 161


🏁 Script executed:

# Read the setupRPC implementation
cat -n packages/devtools/src/server-rpc/index.ts | head -100

Repository: nuxt/devtools

Length of output: 4176


🏁 Script executed:

# Check if devtoolsKit is mentioned and defined as a getter
rg "devtoolsKit" packages/devtools/src/server-rpc/index.ts -B 3 -A 3

Repository: nuxt/devtools

Length of output: 1814


🏁 Script executed:

# Look for where ctx is used after destructuring to understand impact
rg "ctx\." packages/devtools/src/module-main.ts -B 2 -A 2 | head -50

Repository: nuxt/devtools

Length of output: 182


🏁 Script executed:

# See more of setupRPC return statement
rg "return \{" packages/devtools/src/server-rpc/index.ts -A 30 | head -50

Repository: nuxt/devtools

Length of output: 911


🏁 Script executed:

# Check how ctx is used downstream - where is it passed?
rg "setupRPC\(nuxt, options\)" packages/devtools/src/module-main.ts -B 2 -A 15

Repository: nuxt/devtools

Length of output: 521


🏁 Script executed:

# Check if ctx is passed to any setup functions or integrations
rg "ctx\." packages/devtools/src/module-main.ts

Repository: nuxt/devtools

Length of output: 85


🏁 Script executed:

# Find the full return statement and see what setupRPC actually returns
rg "return \{" packages/devtools/src/server-rpc/index.ts -A 5 | tail -20

Repository: nuxt/devtools

Length of output: 249


🏁 Script executed:

# Check if there are any later uses of ctx.devtoolsKit in module-main.ts
rg "devtoolsKit" packages/devtools/src/module-main.ts

Repository: nuxt/devtools

Length of output: 39


🏁 Script executed:

# See if the destructured ctx variable is actually used after the destructuring
sed -n '132,200p' packages/devtools/src/module-main.ts | cat -n

Repository: nuxt/devtools

Length of output: 2956


Preserve the live devtoolsKit accessor.

Object rest destructuring at line 132 materializes the devtoolsKit getter into a plain undefined property before connectDevToolsKit() is called. Since ctx is then passed to integrations (e.g., at lines 64, 67), they all receive a permanently stale devtoolsKit value.

Suggested fix
-  const {
-    connectDevToolsKit: _connectDevToolsKit,
-    ...ctx
-  } = setupRPC(nuxt, options)
-
-  connectDevToolsKit = _connectDevToolsKit
+  const ctx = setupRPC(nuxt, options)
+  connectDevToolsKit = ctx.connectDevToolsKit
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const {
connectRpcHost: _connectRpcHost,
connectDevToolsKit: _connectDevToolsKit,
...ctx
} = setupRPC(nuxt, options)
connectRpcHost = _connectRpcHost
connectDevToolsKit = _connectDevToolsKit
const ctx = setupRPC(nuxt, options)
connectDevToolsKit = ctx.connectDevToolsKit
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/devtools/src/module-main.ts` around lines 132 - 137, The object rest
(`...ctx`) from setupRPC is materializing the devtoolsKit getter into a plain
property, causing integrations that receive ctx to see a stale/undefined
devtoolsKit; instead, keep the original object returned by setupRPC so the live
getter is preserved: call const fullCtx = setupRPC(nuxt, options), set
connectDevToolsKit = fullCtx.connectDevToolsKit (or extract _connectDevToolsKit
from fullCtx), and pass fullCtx (not the spread ctx) into integrations and other
consumers so devtoolsKit remains a live accessor; reference setupRPC,
connectDevToolsKit/_connectDevToolsKit, devtoolsKit, and ctx in the change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant