A VS Code extension that answers "where is this .vue component used?" for Nuxt
projects with auto-imported components — the case the built-in tooling and
Volar's file-references can't reliably do.
- A CodeLens on the
<template>tag:N references. - Clicking it opens the floating peek window with every usage.
- cmd/ctrl+click on the
<template>tag jumps to usages (single usage navigates; multiple opens a peek list).
How it works
Every source file is AST-scanned (@vue/compiler-sfc for templates,
@babel/parser for scripts) into one targetVueFile -> usage locations index:
- Template tags (primary). Component tags resolve first against the file's
own default imports (
import Foo from './Foo.vue'→<Foo/>/<foo/>), then against Nuxt's generatedcomponents.d.ts— the authoritative component-name -> file map (so<BaseButton/>, kebab<base-button/>, and shadcn<Button/>all resolve exactly as Nuxt resolves them).<component :is="Foo">/:is="'foo-card'"resolve too whenisis a static string, a string literal, or a locally imported / registry name. - Imports.
importspecifiers (incl. dynamic imports and re-exports) resolve via relative paths +tsconfig/jsconfig/.nuxt/tsconfig.json/ Nuxt 4.1+.nuxt/tsconfig.app.jsonaliases, covering composables and components imported from.ts/.jsfiles.
A FileSystemWatcher reindexes changed files incrementally; a second watcher
reloads the registry whenever Nuxt regenerates components.d.ts.
Requirements
Because the primary path relies on components.d.ts, run the dev server (or
nuxt prepare) at least once so .nuxt/[types/]components.d.ts exists. It
supports both the classic .nuxt/components.d.ts and the Nuxt 4.1+
.nuxt/types/components.d.ts location (including the off-by-one relative-path
quirk) by resolving each entry against disk.
Count semantics
References are <Tag> occurrences across templates — for auto-imported and
explicitly imported components alike, so navigation always lands on a real
usage. An import site itself only counts when the importing file doesn't use
the component in its template (e.g. route configs, defineAsyncComponent
wrappers, re-exports).
Run it
npm install
npm run compile # or: npm run watch
npm test # headless suite against the fixture repos in test/
Press F5 to launch an Extension Development Host, open your Nuxt repo there,
open any component under components/.
Package / install locally
npm run deploy # typecheck + esbuild bundle + vsce package
code --install-extension vue-component-references-0.1.0.vsix
Settings
| Setting | Default | Purpose |
|---|---|---|
vueRefs.include |
**/*.{vue,ts,js,mjs,cjs,tsx,jsx} |
Files scanned |
vueRefs.exclude |
**/{node_modules,dist,.nuxt,.output,.git,coverage}/** |
Ignored files |
vueRefs.scanTemplates |
true |
Resolve <Tag> usages via components.d.ts (auto-imports) |
vueRefs.maxFileSizeKB |
512 |
Skip files larger than this while indexing (0 = no limit) |
Command palette: "Vue Refs: Rebuild reference index" to force a full rebuild.
Performance
The index is cached per workspace (mtime-invalidated), so after the first cold build (~seconds on a large monorepo, non-blocking) subsequent startups restore in milliseconds and only changed files re-scan. Each rebuild logs a timing summary to the Vue Component References output channel.
Limits / next steps
<component :is="someExpression">with a computed/dynamic expression can't be resolved statically (literals and identifier bindings are handled).- Namespaced/icon component names (
IconMdi:check) from unplugin-icons are parsed but won't match ordinary tag scans; harmless.