--- name: lifecycle-hooks description: Nuxt and Nitro hooks for extending build-time and runtime behavior --- # Lifecycle Hooks Nuxt provides hooks to tap into the build process, application lifecycle, and server runtime. ## Build-time Hooks (Nuxt) Used in `nuxt.config.ts` or modules: ### In nuxt.config.ts ```ts // nuxt.config.ts export default defineNuxtConfig({ hooks: { 'build:before': () => { console.log('Build starting...') }, 'pages:extend': (pages) => { // Add custom pages pages.push({ name: 'custom', path: '/custom', file: '~/pages/custom.vue', }) }, 'components:dirs': (dirs) => { // Add component directories dirs.push({ path: '~/extra-components' }) }, }, }) ``` ### In Modules ```ts // modules/my-module.ts export default defineNuxtModule({ setup(options, nuxt) { nuxt.hook('ready', async (nuxt) => { console.log('Nuxt is ready') }) nuxt.hook('close', async (nuxt) => { console.log('Nuxt is closing') }) nuxt.hook('modules:done', () => { console.log('All modules loaded') }) }, }) ``` ### Common Build Hooks | Hook | When | |------|------| | `ready` | Nuxt initialization complete | | `close` | Nuxt is closing | | `modules:done` | All modules installed | | `build:before` | Before build starts | | `build:done` | Build complete | | `pages:extend` | Pages routes resolved | | `components:dirs` | Component dirs being resolved | | `imports:extend` | Auto-imports being resolved | | `nitro:config` | Before Nitro config finalized | | `vite:extend` | Vite context created | | `vite:extendConfig` | Before Vite config finalized | ## App Hooks (Runtime) Used in plugins and composables: ### In Plugins ```ts // plugins/lifecycle.ts export default defineNuxtPlugin((nuxtApp) => { nuxtApp.hook('app:created', (vueApp) => { console.log('Vue app created') }) nuxtApp.hook('app:mounted', (vueApp) => { console.log('App mounted') }) nuxtApp.hook('page:start', () => { console.log('Page navigation starting') }) nuxtApp.hook('page:finish', () => { console.log('Page navigation finished') }) nuxtApp.hook('page:loading:start', () => { console.log('Page loading started') }) nuxtApp.hook('page:loading:end', () => { console.log('Page loading ended') }) }) ``` ### Common App Hooks | Hook | When | |------|------| | `app:created` | Vue app created | | `app:mounted` | Vue app mounted (client only) | | `app:error` | Fatal error occurred | | `page:start` | Page navigation starting | | `page:finish` | Page navigation finished | | `page:loading:start` | Loading indicator should show | | `page:loading:end` | Loading indicator should hide | | `link:prefetch` | Link is being prefetched | ### Using Runtime Hooks ```ts // composables/usePageTracking.ts export function usePageTracking() { const nuxtApp = useNuxtApp() nuxtApp.hook('page:finish', () => { trackPageView(useRoute().path) }) } ``` ## Server Hooks (Nitro) Used in server plugins: ```ts // server/plugins/hooks.ts export default defineNitroPlugin((nitroApp) => { // Modify HTML before sending nitroApp.hooks.hook('render:html', (html, { event }) => { html.head.push('') html.bodyAppend.push('') }) // Modify response nitroApp.hooks.hook('render:response', (response, { event }) => { console.log('Sending response:', response.statusCode) }) // Before request nitroApp.hooks.hook('request', (event) => { console.log('Request:', event.path) }) // After response nitroApp.hooks.hook('afterResponse', (event) => { console.log('Response sent') }) }) ``` ### Common Nitro Hooks | Hook | When | |------|------| | `request` | Request received | | `beforeResponse` | Before sending response | | `afterResponse` | After response sent | | `render:html` | Before HTML is sent | | `render:response` | Before response is finalized | | `error` | Error occurred | ## Custom Hooks ### Define Custom Hook Types ```ts // types/hooks.d.ts import type { HookResult } from '@nuxt/schema' declare module '#app' { interface RuntimeNuxtHooks { 'my-app:event': (data: MyEventData) => HookResult } } declare module '@nuxt/schema' { interface NuxtHooks { 'my-module:init': () => HookResult } } declare module 'nitropack/types' { interface NitroRuntimeHooks { 'my-server:event': (data: any) => void } } ``` ### Call Custom Hooks ```ts // In a plugin export default defineNuxtPlugin((nuxtApp) => { // Call custom hook nuxtApp.callHook('my-app:event', { type: 'custom' }) }) // In a module export default defineNuxtModule({ setup(options, nuxt) { nuxt.callHook('my-module:init') }, }) ``` ## useRuntimeHook Call hooks at runtime from components: ```vue ``` ## Hook Examples ### Page View Tracking ```ts // plugins/analytics.client.ts export default defineNuxtPlugin((nuxtApp) => { nuxtApp.hook('page:finish', () => { const route = useRoute() analytics.track('pageview', { path: route.path, title: document.title, }) }) }) ``` ### Performance Monitoring ```ts // plugins/performance.client.ts export default defineNuxtPlugin((nuxtApp) => { let navigationStart: number nuxtApp.hook('page:start', () => { navigationStart = performance.now() }) nuxtApp.hook('page:finish', () => { const duration = performance.now() - navigationStart console.log(`Navigation took ${duration}ms`) }) }) ``` ### Inject HTML ```ts // server/plugins/inject.ts export default defineNitroPlugin((nitroApp) => { nitroApp.hooks.hook('render:html', (html) => { html.head.push(` `) }) }) ```