0
# Component Resolution
1
2
Built-in component discovery from directories and extensible resolver system for UI libraries, with support for custom resolution logic and namespace management.
3
4
## Capabilities
5
6
### Component Discovery
7
8
Automatic component discovery from configured directories with flexible naming and namespace support.
9
10
```typescript { .api }
11
/**
12
* Component discovery configuration
13
*/
14
interface ComponentDiscoveryOptions {
15
/** Directories to search for components */
16
dirs?: string | string[];
17
/** File extensions to consider as components */
18
extensions?: string | string[];
19
/** Search subdirectories recursively */
20
deep?: boolean;
21
/** Use directory structure as component namespaces */
22
directoryAsNamespace?: boolean;
23
/** Component name prefix */
24
prefix?: string;
25
}
26
```
27
28
**Usage Examples:**
29
30
```typescript
31
// Basic directory discovery
32
Components({
33
dirs: ["src/components"],
34
extensions: ["vue", "tsx"],
35
deep: true,
36
});
37
38
// With namespacing
39
Components({
40
dirs: ["src/components"],
41
directoryAsNamespace: true,
42
// src/components/form/Input.vue becomes <FormInput>
43
});
44
```
45
46
### Custom Resolvers
47
48
Extensible resolver system for custom component resolution logic, supporting both function-based and object-based resolvers.
49
50
```typescript { .api }
51
/**
52
* Function-based component resolver
53
* @param name - Component name to resolve
54
* @returns Component resolution result
55
*/
56
type ComponentResolverFunction = (name: string) => ComponentResolveResult;
57
58
/**
59
* Object-based component resolver with type specification
60
*/
61
interface ComponentResolverObject {
62
/** Type of items this resolver handles */
63
type: "component" | "directive";
64
/** Resolution function */
65
resolve: ComponentResolverFunction;
66
}
67
68
/**
69
* Union type for all resolver types
70
*/
71
type ComponentResolver = ComponentResolverFunction | ComponentResolverObject;
72
73
/**
74
* Result of component resolution
75
*/
76
type ComponentResolveResult = Awaitable<string | ComponentInfo | null | undefined | void>;
77
78
/**
79
* Component information returned by resolvers
80
*/
81
interface ComponentInfo {
82
/** Import alias name */
83
as?: string;
84
/** Component name */
85
name?: string;
86
/** Import path or module name */
87
from: string;
88
/** Side effect imports (CSS, etc.) */
89
sideEffects?: SideEffectsInfo;
90
}
91
92
type SideEffectsInfo = (ImportInfo | string)[] | ImportInfo | string | undefined;
93
94
interface ImportInfo {
95
as?: string;
96
name?: string;
97
from: string;
98
}
99
```
100
101
**Usage Examples:**
102
103
```typescript
104
// Function-based resolver
105
Components({
106
resolvers: [
107
(name: string) => {
108
if (name.startsWith("My")) {
109
return {
110
name,
111
from: `@/components/${name}.vue`,
112
};
113
}
114
},
115
],
116
});
117
118
// Object-based resolver with type
119
Components({
120
resolvers: [
121
{
122
type: "component",
123
resolve: (name: string) => {
124
if (name.match(/^V[A-Z]/)) {
125
return {
126
name,
127
from: "vuetify/components",
128
sideEffects: "vuetify/styles",
129
};
130
}
131
},
132
},
133
],
134
});
135
```
136
137
### Resolver Chaining
138
139
Multiple resolvers can be configured and will be called in order until one returns a result.
140
141
```typescript { .api }
142
/**
143
* Multiple resolvers are processed in order
144
*/
145
interface ResolverChainOptions {
146
resolvers?: ComponentResolver[];
147
}
148
```
149
150
**Usage Examples:**
151
152
```typescript
153
Components({
154
resolvers: [
155
// First try UI library resolvers
156
ElementPlusResolver(),
157
AntDesignVueResolver(),
158
159
// Then custom business logic
160
(name: string) => {
161
if (name.startsWith("App")) {
162
return { name, from: `@/components/app/${name}.vue` };
163
}
164
},
165
166
// Finally fallback resolver
167
(name: string) => {
168
return { name, from: `@/components/fallback/${name}.vue` };
169
},
170
],
171
});
172
```
173
174
### Advanced Resolution Features
175
176
Advanced features for complex resolution scenarios including conditional resolution and dynamic imports.
177
178
```typescript { .api }
179
/**
180
* Advanced resolver with conditional logic
181
*/
182
interface AdvancedResolverResult {
183
/** Component name override */
184
name?: string;
185
/** Import source */
186
from: string;
187
/** Import alias */
188
as?: string;
189
/** Side effects to import */
190
sideEffects?: SideEffectsInfo;
191
}
192
```
193
194
**Usage Examples:**
195
196
```typescript
197
// Conditional resolution based on environment
198
Components({
199
resolvers: [
200
(name: string) => {
201
// Use different components for different environments
202
if (name === "DataGrid") {
203
const isDev = process.env.NODE_ENV === "development";
204
return {
205
name,
206
from: isDev ? "@/components/dev/DataGrid.vue" : "@/components/prod/DataGrid.vue",
207
};
208
}
209
},
210
],
211
});
212
213
// Dynamic resolution with side effects
214
Components({
215
resolvers: [
216
(name: string) => {
217
if (name.startsWith("Chart")) {
218
return {
219
name,
220
from: "chart-library",
221
sideEffects: [
222
"chart-library/styles/index.css",
223
{ from: "chart-library/themes", name: "defaultTheme" },
224
],
225
};
226
}
227
},
228
],
229
});
230
```
231
232
### Resolution Context
233
234
Access to resolution context for advanced use cases.
235
236
```typescript { .api }
237
/**
238
* Extended resolver function with context
239
*/
240
type ContextualResolverFunction = (
241
name: string,
242
context?: ResolutionContext
243
) => ComponentResolveResult;
244
245
interface ResolutionContext {
246
/** File path where component is being used */
247
filename?: string;
248
/** Additional context information */
249
[key: string]: any;
250
}
251
```
252
253
**Usage Examples:**
254
255
```typescript
256
// Context-aware resolution
257
Components({
258
resolvers: [
259
(name: string, context?: ResolutionContext) => {
260
if (context?.filename?.includes("/admin/")) {
261
// Use admin-specific components
262
return { name, from: `@/components/admin/${name}.vue` };
263
}
264
return { name, from: `@/components/public/${name}.vue` };
265
},
266
],
267
});
268
```
269
270
### Built-in Utilities
271
272
Utility functions commonly used in custom resolvers.
273
274
```typescript { .api }
275
/**
276
* String case conversion utilities
277
*/
278
function camelCase(str: string): string;
279
function kebabCase(str: string): string;
280
function pascalCase(str: string): string;
281
```
282
283
**Usage Examples:**
284
285
```typescript
286
import { camelCase, kebabCase, pascalCase } from "unplugin-vue-components";
287
288
Components({
289
resolvers: [
290
(name: string) => {
291
// Convert PascalCase component name to kebab-case file name
292
const fileName = kebabCase(name);
293
return {
294
name,
295
from: `@/components/${fileName}.vue`,
296
};
297
},
298
],
299
});
300
```
301
302
### Component Name Patterns
303
304
Common patterns for component name resolution and transformation.
305
306
**Usage Examples:**
307
308
```typescript
309
// Prefix-based resolution
310
Components({
311
resolvers: [
312
(name: string) => {
313
// Handle prefixed components: AppButton -> app/Button.vue
314
const match = name.match(/^App(.+)$/);
315
if (match) {
316
return {
317
name,
318
from: `@/components/app/${match[1]}.vue`,
319
};
320
}
321
},
322
],
323
});
324
325
// Namespace-based resolution
326
Components({
327
resolvers: [
328
(name: string) => {
329
// Handle namespaced components: FormInput -> form/Input.vue
330
const parts = name.match(/^([A-Z][a-z]+)([A-Z].+)$/);
331
if (parts) {
332
const [, namespace, component] = parts;
333
return {
334
name,
335
from: `@/components/${namespace.toLowerCase()}/${component}.vue`,
336
};
337
}
338
},
339
],
340
});
341
```
342
343
### Error Handling
344
345
Proper error handling in custom resolvers.
346
347
**Usage Examples:**
348
349
```typescript
350
Components({
351
resolvers: [
352
(name: string) => {
353
try {
354
// Custom resolution logic that might fail
355
if (name.startsWith("External")) {
356
const moduleName = name.replace("External", "").toLowerCase();
357
// Validate module exists
358
require.resolve(`external-components/${moduleName}`);
359
return {
360
name,
361
from: `external-components/${moduleName}`,
362
};
363
}
364
} catch (error) {
365
// Silently fail - let other resolvers handle it
366
return null;
367
}
368
},
369
],
370
});
371
```