When defining configuration schemas, use consistent patterns for safe property access, async resolution, and default value handling. Always use optional chaining with fallback values for nested configuration properties, leverage $resolve
for complex async configuration logic, and ensure proper backwards compatibility.
Key patterns to follow:
const extraKeys = nuxt.options?.experimental?.extraPageMetaExtractionKeys || []
$resolve
for complex configuration logic that requires async operations or cross-property dependencies:
serverDir: {
$resolve: async (val: string | undefined, get): Promise<string> => {
return resolve(await get('rootDir') as string, val ?? 'server')
}
}
defu
for merging configuration objects with proper defaults:
spaLoaderAttrs: {
$resolve: (val: undefined | null | Record<string, unknown>) => {
return defu(val, {
id: val?.id ?? '__nuxt-spa-loader',
})
}
}
propsDestructure: {
$resolve: async (val, get) => {
// Check both new and legacy locations
return val ?? Boolean((await get('vue') as Record<string, any>).propsDestructure)
}
}
undefined
(not set) and null
(explicitly set to null) values:
// Only filter out undefined, preserve null values for runtime override capability
if (typeof obj[key] === 'undefined') {
// handle undefined case
}
This ensures configuration is resolved consistently, safely handles missing values, and maintains backwards compatibility while supporting complex async resolution scenarios.
Enter the URL of a public GitHub repository