nuxt / nuxt/devtools

vite-plugin-vue-tracer breaks virtual layout modules under Vite 8 (Nuxt ≥ 4.5)

Open
#1,051 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
3.3k
Forks
214
Avg merge
13h 22m
Merged PRs (30d)
18

Description

🐛 The bug

When using a named layout registered via addLayout from @nuxt/kit (e.g. from a third-party Nuxt module), the dev server crashes with
an unresolvable import injected by vite-plugin-vue-tracer.

[plugin:vite:import-analysis] Failed to resolve import
"./node_modules/.pnpm/vite-plugin-vue-tracer@1.4.0_.../node_modules/vite-plugin-vue-tracer/dist/client/record.mjs"
from "virtual:nuxt:.nuxt%2Flayouts.default.<hash>.vue". Does the file exist?

This regression was introduced in Nuxt 4.5.0, which upgraded from Vite 7 to Vite 8. Rolling back to Nuxt ≤ 4.4.x (Vite 7) resolves
the error.

🛠️ To reproduce
  1. Use a Nuxt module that calls addLayout to register a named layout (e.g. "ipa-default")
  2. Reference that layout in app.vue:
    <template>
      <NuxtLayout name="ipa-default">
        <NuxtPage />
      </NuxtLayout>
    </template>
    
  3. Keep devtools: { enabled: true } in nuxt.config.ts
  4. Run nuxt dev — error occurs immediately

Removing name="ipa-default" (falling back to the default layout) clears the error.

🌈 Expected behavior

Dev server starts normally; vite-plugin-vue-tracer should not break virtual layout modules.

🔍 Root cause

vite-plugin-vue-tracer (enforce: "post") injects an import at the top of every compiled Vue SFC that matches its heuristics:

import { recordPosition as _tracerRecordPosition } from "./node_modules/.pnpm/vite-plugin-vue-tracer.../record.mjs"

The path is computed as relative(dirname(id), absoluteTracerPath). For real files, dirname(id) is a real directory and the
relative path resolves correctly.

For Nuxt layout virtual modules (ID: virtual:nuxt:.nuxt%2Flayouts.<name>.<hash>.vue), dirname() returns "." (no real
filesystem base), so the relative path becomes ./node_modules/.pnpm/....

  • Vite 7: vite:import-analysis fell back to CWD when resolving relative imports from virtual modules — worked by accident.
  • Vite 8: Stricter resolution; virtual modules without a real filesystem path can no longer resolve relative imports this way →
    error.

This is a follow-up to #805, which fixed the same plugin for real files (app.vue at project root) but did not address virtual module
IDs.

ℹ️ Environment
@nuxt/devtools 3.4.0
vite-plugin-vue-tracer 1.4.0
nuxt 4.5.1 (Vite 8.2.0) — broken
nuxt 4.4.8 (Vite 7.x) — works
OS macOS
💡 Suggested fix

In vite-plugin-vue-tracer, skip virtual module IDs when computing the relative record path, or set resolveRecordEntryPath: false so
the bare specifier "vite-plugin-vue-tracer/client/record" is used instead:

const getRecordPath = (id) => {
  // Virtual modules have no real filesystem base — use bare specifier
  if (!resolveRecordEntryPath || id.startsWith('virtual:') || id.startsWith('\0')) {
    return "vite-plugin-vue-tracer/client/record";
  }
  // ... existing relative path logic
};
🩹 Temporary workaround
  1. pin nuxt 4.4.8, do not upgrade to 4.5.x
  2. llm gives a solution, i did not try

Add a Vite alias in nuxt.config.ts to redirect the injected relative path back to the bare specifier:

vite: {
  resolve: {
    alias: [
      {
        find: /.*vite-plugin-vue-tracer.*\/client\/record\.mjs$/,
        replacement: "vite-plugin-vue-tracer/client/record",
      },
    ],
  },
},

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the failure with a named addLayout layout, app.vue, devtools enabled, and Nuxt 4.5.1, then compare against Nuxt 4.4.8. Start by tracing vite-plugin-vue-tracer's getRecordPath handling of virtual: and \0 IDs and the injected record.mjs import; the work is done when the Nuxt dev server starts and virtual layout modules resolve without the error.

Written by the indexing model from the issue text.

Assessment

Tech stack
nuxt, typescript, vite
Domain
build-system, devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.