feat(kit,nuxt): add component priority to allow overriding (#19252)

This commit is contained in:
Daniel Roe 2023-03-06 11:33:40 +00:00 committed by GitHub
parent a7d75a8465
commit 129bb4fa3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 48 additions and 7 deletions

View File

@ -40,14 +40,24 @@ export async function addComponent (opts: AddComponentOptions) {
preload: false,
mode: 'all',
shortPath: opts.filePath,
priority: 0,
...opts
}
nuxt.hook('components:extend', (components: Component[]) => {
const existingComponent = components.find(c => (c.pascalName === component.pascalName || c.kebabName === component.kebabName) && c.mode === component.mode)
if (existingComponent) {
const existingPriority = existingComponent.priority ?? 0
const newPriority = component.priority ?? 0
if (newPriority < existingPriority) { return }
// We override where new component priority is equal or higher
// but we warn if they are equal.
if (newPriority === existingPriority) {
const name = existingComponent.pascalName || existingComponent.kebabName
console.warn(`Overriding ${name} component.`)
console.warn(`Overriding ${name} component. You can specify a \`priority\` option when calling \`addComponent\` to avoid this warning.`)
}
Object.assign(existingComponent, component)
} else {
components.push(component)

View File

@ -118,7 +118,9 @@ export async function scanComponents (dirs: ComponentsDir[], srcDir: string): Pr
kebabName,
chunkName,
shortPath,
export: 'default'
export: 'default',
// by default, give priority to scanned components
priority: 1
}
if (typeof dir.extendComponent === 'function') {

View File

@ -158,47 +158,55 @@ async function initNuxt (nuxt: Nuxt) {
// Add <NuxtWelcome>
addComponent({
name: 'NuxtWelcome',
priority: 10, // built-in that we do not expect the user to override
filePath: tryResolveModule('@nuxt/ui-templates/templates/welcome.vue')!
})
addComponent({
name: 'NuxtLayout',
priority: 10, // built-in that we do not expect the user to override
filePath: resolve(nuxt.options.appDir, 'components/layout')
})
// Add <NuxtErrorBoundary>
addComponent({
name: 'NuxtErrorBoundary',
priority: 10, // built-in that we do not expect the user to override
filePath: resolve(nuxt.options.appDir, 'components/nuxt-error-boundary')
})
// Add <ClientOnly>
addComponent({
name: 'ClientOnly',
priority: 10, // built-in that we do not expect the user to override
filePath: resolve(nuxt.options.appDir, 'components/client-only')
})
// Add <DevOnly>
addComponent({
name: 'DevOnly',
priority: 10, // built-in that we do not expect the user to override
filePath: resolve(nuxt.options.appDir, 'components/dev-only')
})
// Add <ServerPlaceholder>
addComponent({
name: 'ServerPlaceholder',
priority: 10, // built-in that we do not expect the user to override
filePath: resolve(nuxt.options.appDir, 'components/server-placeholder')
})
// Add <NuxtLink>
addComponent({
name: 'NuxtLink',
priority: 10, // built-in that we do not expect the user to override
filePath: resolve(nuxt.options.appDir, 'components/nuxt-link')
})
// Add <NuxtLoadingIndicator>
addComponent({
name: 'NuxtLoadingIndicator',
priority: 10, // built-in that we do not expect the user to override
filePath: resolve(nuxt.options.appDir, 'components/nuxt-loading-indicator')
})
@ -206,6 +214,7 @@ async function initNuxt (nuxt: Nuxt) {
if (nuxt.options.experimental.componentIslands) {
addComponent({
name: 'NuxtIsland',
priority: 10, // built-in that we do not expect the user to override
filePath: resolve(nuxt.options.appDir, 'components/nuxt-island')
})
}

View File

@ -24,6 +24,8 @@ export default defineNuxtModule({
name: componentName,
filePath: componentsPath,
export: componentName,
// built-in that we do not expect the user to override
priority: 10,
// kebab case version of these tags is not valid
kebabName: componentName
})

View File

@ -43,6 +43,7 @@ export default defineNuxtModule({
})
addComponent({
name: 'NuxtPage',
priority: 10, // built-in that we do not expect the user to override
filePath: resolve(distDir, 'pages/runtime/page-placeholder')
})
return
@ -256,6 +257,7 @@ export default defineNuxtModule({
// Add <NuxtPage>
addComponent({
name: 'NuxtPage',
priority: 10, // built-in that we do not expect the user to override
filePath: resolve(distDir, 'pages/runtime/page')
})

View File

@ -97,6 +97,7 @@ const expectedComponents = [
pascalName: 'Isle',
prefetch: false,
preload: false,
priority: 1,
shortPath: 'components/islands/Isle.vue'
},
{
@ -109,6 +110,7 @@ const expectedComponents = [
pascalName: 'Glob',
prefetch: false,
preload: false,
priority: 1,
shortPath: 'components/global/Glob.vue'
},
{
@ -121,7 +123,8 @@ const expectedComponents = [
global: undefined,
island: undefined,
prefetch: false,
preload: false
preload: false,
priority: 1
},
{
mode: 'client',
@ -133,7 +136,8 @@ const expectedComponents = [
global: undefined,
island: undefined,
prefetch: false,
preload: false
preload: false,
priority: 1
},
{
mode: 'server',
@ -145,7 +149,8 @@ const expectedComponents = [
global: undefined,
island: undefined,
prefetch: false,
preload: false
preload: false,
priority: 1
},
{
chunkName: 'components/client-component-with-props',
@ -157,6 +162,7 @@ const expectedComponents = [
pascalName: 'ClientComponentWithProps',
prefetch: false,
preload: false,
priority: 1,
shortPath: 'components/client/ComponentWithProps.vue'
},
{
@ -169,6 +175,7 @@ const expectedComponents = [
pascalName: 'ClientWithClientOnlySetup',
prefetch: false,
preload: false,
priority: 1,
shortPath: 'components/client/WithClientOnlySetup.vue'
},
{
@ -181,7 +188,8 @@ const expectedComponents = [
global: undefined,
island: undefined,
prefetch: false,
preload: false
preload: false,
priority: 1
},
{
chunkName: 'components/some-glob',
@ -193,6 +201,7 @@ const expectedComponents = [
pascalName: 'SomeGlob',
prefetch: false,
preload: false,
priority: 1,
shortPath: 'components/some-glob.global.vue'
},
{
@ -205,6 +214,7 @@ const expectedComponents = [
pascalName: 'Some',
prefetch: false,
preload: false,
priority: 1,
shortPath: 'components/some.island.vue'
}
]

View File

@ -10,6 +10,12 @@ export interface Component {
global?: boolean
island?: boolean
mode?: 'client' | 'server' | 'all'
/**
* This number allows configuring the behavior of overriding Nuxt components.
* If multiple components are provided with the same name, then higher priority
* components will be used instead of lower priority components.
*/
priority?: number
}
export interface ScanDir {