Components Auto-discovery
Relevant source files
The following files were used as context for generating this wiki page:
Components Auto-discovery is a core Nuxt feature that automates the registration of Vue components. By scanning specific directories (primarily components/), Nuxt identifies components and makes them available globally or for auto-importing throughout the application, eliminating the need for manual import statements in pages, layouts, and other components. Sources: packages/schema/src/types/schema.ts:32-37, README.md:27-27
The system is designed to be extensible, allowing modules to contribute their own component directories or individual components. It handles various rendering modes, including standard Vue components, client-only components, server-only components, and "component islands" for hybrid rendering architectures. Sources: packages/nuxt/src/core/nuxt.ts:600-685, packages/nuxt/src/components/templates.ts:98-142
Component Scanning Logic
The scanning process is the primary mechanism for identifying local components. Nuxt iterates through a list of configured directories, searching for files that match specified patterns (typically Vue, TS, and JS files). Sources: packages/nuxt/src/components/scan.ts:24-30
Resolution and Naming
When a file is discovered, Nuxt derives a PascalCase name based on its path relative to the scanning directory and its filename. If a file is named index, its name is derived from the parent directory. Sources: packages/nuxt/src/components/scan.ts:88-103
The following naming and metadata rules apply during scanning:
- Suffix Detection: Files ending in
.clientor.serverare assigned to specific modes. Sources: packages/nuxt/src/components/scan.ts:92-93 - Island Components: Files ending in
.islandare treated as server-side components intended for use with Nuxt Islands. Sources: packages/nuxt/src/components/scan.ts:91-92 - Global Registration: Files ending in
.globalare automatically registered globally in the Vue application. Sources: packages/nuxt/src/components/scan.ts:92-93
The Scanning Workflow
The following diagram illustrates the logical flow of scanning a single directory for components.
Component Data Structure
Scanned components are stored in a standard internal object format defined in the Nuxt schema. Sources: packages/nuxt/src/components/scan.ts:121-140
| Field | Description |
|---|---|
pascalName | The generated name used for auto-imports and templates (e.g., MyButton). |
mode | The rendering environment: 'all', 'client', or 'server'. |
global | Boolean indicating if the component is registered globally via app.component. |
island | Boolean indicating if the component is an island component. |
filePath | The absolute path to the source file. |
chunkName | The name of the chunk used by the bundler (e.g., components/my-button). |
priority | Numeric value to resolve naming conflicts between different sources. |
Sources: packages/nuxt/src/components/scan.ts:121-140
Template Generation and Typing
Nuxt generates several virtual files to support auto-discovery at runtime and provide type safety for developers. These are managed via the Nuxt Template system. Sources: packages/nuxt/src/components/templates.ts:178-278, packages/nuxt/src/core/templates.ts:93-108
components.d.ts
This template generates TypeScript declarations for all discovered components. It provides global exports for standard components and their "Lazy" (dynamically imported) counterparts. Sources: packages/nuxt/src/components/templates.ts:192-212
types/components.d.ts
This template augments the GlobalComponents interface in Vue, ensuring that components used in templates without imports are correctly typed by IDEs and vue-tsc. Sources: packages/nuxt/src/components/templates.ts:214-256
components.plugin.mjs
A runtime plugin that registers components marked as global. It handles both synchronous registration and lazy registration (using defineAsyncComponent). Sources: packages/nuxt/src/components/templates.ts:40-75
Component Islands (Experimental)
When experimental.componentIslands is enabled, Nuxt discovers components that should be rendered exclusively on the server but remain interactive on the client through the Island architecture. Sources: packages/nuxt/src/components/templates.ts:98-101
- Island Recognition: Components are identified as islands if they have the
.islandsuffix or if they are.servercomponents without a corresponding.clientpair. Sources: packages/nuxt/src/components/templates.ts:108-112 - Island Template: Nuxt generates
components.islands.mjs, which maps island names todefineAsyncComponentcalls that point to the server-side rendering logic. Sources: packages/nuxt/src/components/templates.ts:122-126 - Client-side Placeholders: On the client, island components are handled as placeholders that fetch their rendered HTML from the server. Sources: packages/nuxt/src/components/templates.ts:133-142
Error Handling and Diagnostics
The componentDiagnostics system provides specific error codes for common configuration or scanning issues. Sources: packages/kit/src/diagnostics/components.ts:11-85
- NUXT_B3008: Triggered by directory casing mismatches (e.g.,
Components/instead ofcomponents/on case-insensitive filesystems). Sources: packages/kit/src/kit-diagnostics:60-64 - NUXT_B3009: Warns when a component name starts with the reserved "Lazy" prefix, which conflicts with Nuxt's auto-generated dynamic import names. Sources: packages/kit/src/kit-diagnostics:65-69
- NUXT_B3011: Emitted when two different files resolve to the same PascalCase component name. Sources: packages/kit/src/kit-diagnostics:75-79
Conclusion
Components Auto-discovery significantly reduces boilerplate by linking the file system structure directly to Vue's component registration. By integrating scanning, template-based type generation, and specific rendering modes (Client, Server, Islands), Nuxt provides a seamless development experience where components are "just available" while maintaining high technical precision and performance through code-splitting. Sources: packages/nuxt/src/core/nuxt.ts:600-750, packages/schema/src/types/schema.ts:32-37