0
# Component System
1
2
The component system in @nuxt/schema provides type definitions for Nuxt's component auto-registration and management system, enabling type-safe component discovery, registration, and configuration.
3
4
## Core Component Types
5
6
### Component Interface
7
8
Represents a registered component with its metadata and configuration.
9
10
```typescript { .api }
11
interface Component {
12
pascalName: string
13
kebabName: string
14
export: string
15
filePath: string
16
shortPath: string
17
chunkName: string
18
prefetch: boolean
19
preload: boolean
20
global?: boolean | 'sync'
21
island?: boolean
22
meta?: ComponentMeta
23
mode?: 'client' | 'server' | 'all'
24
priority?: number
25
/** @internal Allow bypassing transforms */
26
_raw?: boolean
27
}
28
```
29
30
### ComponentMeta Interface
31
32
Extensible metadata for components.
33
34
```typescript { .api }
35
interface ComponentMeta {
36
[key: string]: unknown
37
}
38
```
39
40
## Component Directory Configuration
41
42
### ScanDir Interface
43
44
Configuration for component directory scanning.
45
46
```typescript { .api }
47
interface ScanDir {
48
/** Path to directory containing components */
49
path: string
50
/** Pattern to match component files */
51
pattern?: string | string[]
52
/** Patterns to ignore */
53
ignore?: string[]
54
/** Prefix for matched components */
55
prefix?: string
56
/** Global registration mode */
57
global?: boolean | 'sync'
58
/** Island component support */
59
island?: boolean
60
/** Component loading mode */
61
mode?: 'client' | 'server' | 'all'
62
/** Priority for component resolution */
63
priority?: number
64
/** Whether to watch for changes */
65
watch?: boolean
66
/** Extensions to scan */
67
extensions?: string[]
68
/** Path prefix for component names */
69
pathPrefix?: boolean
70
}
71
```
72
73
### ComponentsDir Interface
74
75
Extended component directory configuration.
76
77
```typescript { .api }
78
interface ComponentsDir extends ScanDir {
79
/** Whether this directory is enabled */
80
enabled?: boolean
81
/** Component prefix to apply */
82
prefix?: string
83
/** Override global setting */
84
global?: boolean | 'sync'
85
}
86
```
87
88
### ComponentsOptions Interface
89
90
Complete components system configuration.
91
92
```typescript { .api }
93
interface ComponentsOptions {
94
/** Component directories to scan */
95
dirs: (string | ComponentsDir)[]
96
/** Global components loader */
97
loader?: boolean
98
/** Transform options */
99
transform?: {
100
/** Include patterns */
101
include?: RegExp[]
102
/** Exclude patterns */
103
exclude?: RegExp[]
104
}
105
/** Whether to generate types */
106
types?: boolean
107
}
108
```
109
110
## Component Registration Patterns
111
112
### Basic Component Registration
113
114
```typescript
115
// nuxt.config.ts
116
export default defineNuxtConfig({
117
components: {
118
dirs: [
119
// Default components directory
120
'~/components',
121
122
// Additional directory with prefix
123
{
124
path: '~/components/ui',
125
prefix: 'UI'
126
},
127
128
// Global components
129
{
130
path: '~/components/global',
131
global: true
132
}
133
]
134
}
135
});
136
```
137
138
### Advanced Component Configuration
139
140
```typescript
141
import type { ComponentsOptions } from '@nuxt/schema';
142
143
const componentsConfig: ComponentsOptions = {
144
dirs: [
145
{
146
path: '~/components/base',
147
prefix: 'Base',
148
global: false,
149
watch: true,
150
extensions: ['vue', 'tsx'],
151
pattern: '**/*.{vue,tsx}',
152
ignore: ['**/*.stories.{js,ts}']
153
},
154
155
{
156
path: '~/components/islands',
157
island: true,
158
mode: 'server',
159
priority: 10
160
},
161
162
{
163
path: '~/components/client',
164
mode: 'client',
165
prefix: 'Client',
166
pathPrefix: false
167
}
168
],
169
170
loader: true,
171
types: true,
172
173
transform: {
174
include: [/\.vue$/, /\.tsx?$/],
175
exclude: [/\.test\./]
176
}
177
};
178
```
179
180
## Component Discovery and Registration
181
182
### Programmatic Component Registration
183
184
```typescript
185
import type { Component } from '@nuxt/schema';
186
187
// In a Nuxt module
188
export default defineNuxtModule({
189
setup(options, nuxt) {
190
// Register components programmatically
191
nuxt.hook('components:extend', (components: Component[]) => {
192
components.push({
193
pascalName: 'MyCustomButton',
194
kebabName: 'my-custom-button',
195
export: 'default',
196
filePath: path.resolve(__dirname, './runtime/components/MyButton.vue'),
197
shortPath: 'runtime/components/MyButton.vue',
198
chunkName: 'components/my-custom-button',
199
prefetch: false,
200
preload: false,
201
global: true,
202
mode: 'all',
203
priority: 0
204
});
205
206
// Register component with metadata
207
components.push({
208
pascalName: 'IconButton',
209
kebabName: 'icon-button',
210
export: 'default',
211
filePath: './components/IconButton.vue',
212
shortPath: 'components/IconButton.vue',
213
chunkName: 'components/icon-button',
214
prefetch: true,
215
preload: true,
216
meta: {
217
category: 'ui',
218
version: '1.0.0',
219
props: ['icon', 'size', 'variant']
220
}
221
});
222
});
223
}
224
});
225
```
226
227
### Component Directory Registration
228
229
```typescript
230
// In a Nuxt module or plugin
231
export default defineNuxtModule({
232
setup(options, nuxt) {
233
// Add component directories
234
nuxt.hook('components:dirs', (dirs) => {
235
dirs.push({
236
path: path.resolve(__dirname, './components'),
237
prefix: options.prefix || 'Module',
238
global: options.global || false,
239
watch: nuxt.options.dev,
240
extensions: ['vue', 'ts', 'tsx'],
241
pattern: '**/*.{vue,ts,tsx}',
242
ignore: ['**/*.story.*', '**/*.test.*']
243
});
244
});
245
}
246
});
247
```
248
249
## Component Type Generation
250
251
### Automatic Type Generation
252
253
```typescript
254
// Types are automatically generated for registered components
255
declare module '@vue/runtime-core' {
256
export interface GlobalComponents {
257
// Auto-registered components
258
MyCustomButton: typeof import('~/components/MyCustomButton.vue')['default']
259
UICard: typeof import('~/components/ui/Card.vue')['default']
260
261
// Island components
262
ServerOnlyChart: typeof import('~/components/islands/Chart.vue')['default']
263
}
264
}
265
```
266
267
### Custom Component Types
268
269
```typescript
270
// In a module setup
271
addTypeTemplate({
272
filename: 'components.d.ts',
273
getContents: ({ nuxt }) => {
274
const components = nuxt.apps.default?.components || [];
275
276
return `
277
declare module '@vue/runtime-core' {
278
export interface GlobalComponents {
279
${components.map(c =>
280
`${c.pascalName}: typeof import('${c.filePath}')['${c.export}']`
281
).join('\n ')}
282
}
283
}
284
285
declare module '#components' {
286
${components.map(c =>
287
`export const ${c.pascalName}: typeof import('${c.filePath}')['${c.export}']`
288
).join('\n ')}
289
}
290
`;
291
}
292
});
293
```
294
295
## Component Loading Modes
296
297
### Client-Side Components
298
299
```typescript
300
const clientComponent: Component = {
301
pascalName: 'ClientOnlyWidget',
302
kebabName: 'client-only-widget',
303
export: 'default',
304
filePath: '~/components/ClientWidget.vue',
305
shortPath: 'components/ClientWidget.vue',
306
chunkName: 'components/client-widget',
307
mode: 'client', // Only loaded on client
308
prefetch: false,
309
preload: false
310
};
311
```
312
313
### Server Components
314
315
```typescript
316
const serverComponent: Component = {
317
pascalName: 'ServerChart',
318
kebabName: 'server-chart',
319
export: 'default',
320
filePath: '~/components/islands/Chart.vue',
321
shortPath: 'components/islands/Chart.vue',
322
chunkName: 'components/server-chart',
323
mode: 'server', // Server-side only
324
island: true, // Island component
325
prefetch: false,
326
preload: false
327
};
328
```
329
330
### Island Components
331
332
```typescript
333
// Enable island components in config
334
export default defineNuxtConfig({
335
experimental: {
336
componentIslands: true
337
},
338
339
components: {
340
dirs: [
341
{
342
path: '~/components/islands',
343
island: true,
344
mode: 'server'
345
}
346
]
347
}
348
});
349
350
// Usage in templates
351
// <ServerChart :data="chartData" />
352
```
353
354
## Component Utilities
355
356
### Component Priority and Resolution
357
358
```typescript
359
// Higher priority components override lower priority ones
360
const highPriorityComponent: Component = {
361
pascalName: 'Button',
362
// ... other properties
363
priority: 10 // Higher number = higher priority
364
};
365
366
const defaultComponent: Component = {
367
pascalName: 'Button',
368
// ... other properties
369
priority: 0 // Default priority
370
};
371
```
372
373
### Component Chunking and Performance
374
375
```typescript
376
const optimizedComponent: Component = {
377
pascalName: 'HeavyChart',
378
kebabName: 'heavy-chart',
379
export: 'default',
380
filePath: '~/components/charts/HeavyChart.vue',
381
shortPath: 'components/charts/HeavyChart.vue',
382
chunkName: 'components/heavy-chart',
383
prefetch: true, // Prefetch when likely to be used
384
preload: false, // Don't preload immediately
385
global: false // Only load when imported
386
};
387
```
388
389
### Component Metadata Usage
390
391
```typescript
392
// In a Nuxt module
393
nuxt.hook('components:extend', (components) => {
394
components.forEach(component => {
395
if (component.meta?.category === 'ui') {
396
// Apply UI-specific transformations
397
component.chunkName = `ui/${component.chunkName}`;
398
component.prefetch = true;
399
}
400
401
if (component.meta?.version) {
402
// Version-based handling
403
console.log(`Component ${component.pascalName} v${component.meta.version}`);
404
}
405
});
406
});
407
```
408
409
The component system provides a flexible and type-safe way to manage component registration, loading, and optimization in Nuxt applications, with full support for different rendering modes and performance optimizations.