feat(nuxt): register plugin hooks before executing plugins (#27449)

This commit is contained in:
Hendrik Heil 2024-06-10 20:41:36 +02:00 committed by GitHub
parent 7d48d98f62
commit 1d34594b9e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 44 additions and 3 deletions

View File

@ -81,8 +81,9 @@ Watch a video from Alexander Lichter about the Object Syntax for Nuxt plugins.
:: ::
::note ::note
If you are using the object-syntax, the properties may be statically analyzed in future to produce a more optimized build. So you should not define them at runtime. :br If you are using the object-syntax, the properties are statically analyzed to produce a more optimized build. So you should not define them at runtime. :br
For example, setting `enforce: import.meta.server ? 'pre' : 'post'` would defeat any future optimization Nuxt is able to do for your plugins. For example, setting `enforce: import.meta.server ? 'pre' : 'post'` would defeat any future optimization Nuxt is able to do for your plugins.
Nuxt does statically pre-load any hook listeners when using object-syntax, allowing you to define hooks without needing to worry about order of plugin registration.
:: ::
## Registration Order ## Registration Order

View File

@ -387,11 +387,15 @@ export function createNuxtApp (options: CreateOptions) {
return nuxtApp return nuxtApp
} }
/** @since 3.0.0 */ /** @since 3.12.0 */
export async function applyPlugin (nuxtApp: NuxtApp, plugin: Plugin & ObjectPlugin<any>) { export function registerPluginHooks (nuxtApp: NuxtApp, plugin: Plugin & ObjectPlugin<any>) {
if (plugin.hooks) { if (plugin.hooks) {
nuxtApp.hooks.addHooks(plugin.hooks) nuxtApp.hooks.addHooks(plugin.hooks)
} }
}
/** @since 3.0.0 */
export async function applyPlugin (nuxtApp: NuxtApp, plugin: Plugin & ObjectPlugin<any>) {
if (typeof plugin === 'function') { if (typeof plugin === 'function') {
const { provide } = await nuxtApp.runWithContext(() => plugin(nuxtApp)) || {} const { provide } = await nuxtApp.runWithContext(() => plugin(nuxtApp)) || {}
if (provide && typeof provide === 'object') { if (provide && typeof provide === 'object') {
@ -438,6 +442,11 @@ export async function applyPlugins (nuxtApp: NuxtApp, plugins: Array<Plugin & Ob
} }
} }
for (const plugin of plugins) {
if (import.meta.server && nuxtApp.ssrContext?.islandContext && plugin.env?.islands === false) { continue }
registerPluginHooks(nuxtApp, plugin)
}
for (const plugin of plugins) { for (const plugin of plugins) {
if (import.meta.server && nuxtApp.ssrContext?.islandContext && plugin.env?.islands === false) { continue } if (import.meta.server && nuxtApp.ssrContext?.islandContext && plugin.env?.islands === false) { continue }
await executePlugin(plugin) await executePlugin(plugin)

View File

@ -283,3 +283,34 @@ describe('plugin dependsOn', () => {
]) ])
}) })
}) })
describe('plugin hooks', () => {
it('registers hooks before executing plugins', async () => {
const nuxtApp = useNuxtApp()
const sequence: string[] = []
const plugins = [
defineNuxtPlugin({
name: 'A',
setup (nuxt) {
sequence.push('start A')
nuxt.callHook('a:setup')
},
}),
defineNuxtPlugin({
name: 'B',
hooks: {
'a:setup': () => {
sequence.push('listen B')
},
},
}),
]
await applyPlugins(nuxtApp, plugins)
expect(sequence).toMatchObject([
'start A',
'listen B',
])
})
})