Skip to content

生命周期钩子

Nuxt 提供三层钩子系统,各层在不同时机执行:

层级执行时机典型用途
App Hooks运行时(客户端 + 服务端)页面加载动画、错误上报、路由拦截
Nuxt Hooks构建时添加页面/组件、修改配置、代码生成
Nitro Hooks服务端运行时请求日志、响应修改、错误处理

为什么需要三层?

App Hooks 处理用户交互和页面生命周期,Nuxt Hooks 处理构建时的代码生成和配置修改,Nitro Hooks 处理服务端请求生命周期。职责分离,避免混乱。

App Hooks

在客户端和服务端运行,用于应用级事件。最常在插件中使用。

在插件中使用

ts
export default defineNuxtPlugin((nuxtApp) => {
  // 页面加载
  nuxtApp.hook('page:start', () => {
    console.log('页面开始加载')
  })

  nuxtApp.hook('page:finish', () => {
    console.log('页面加载完成')
  })

  // 应用挂载(仅客户端)
  nuxtApp.hook('app:mounted', () => {
    console.log('应用已挂载')
  })

  // 错误
  nuxtApp.hook('vue:error', (error, instance, info) => {
    console.error('Vue 错误:', error)
  })

  nuxtApp.hook('app:error', (error) => {
    console.error('应用错误:', error)
  })
})

实用示例

页面加载进度条

ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook('page:start', () => {
    NProgress.start()  // 显示加载条
  })
  nuxtApp.hook('page:finish', () => {
    NProgress.done()   // 隐藏加载条
  })
})

全局错误上报到 Sentry

ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook('vue:error', (error) => {
    Sentry.captureException(error)
  })
  nuxtApp.hook('app:error', (error) => {
    Sentry.captureException(error)
  })
})

自定义链接预取

ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook('link:prefetch', ({ to }) => {
    // 只预取特定路径
    if (to.startsWith('/blog')) return true
    return false  // 其他路径不预取
  })
})

常用 App Hooks

钩子参数说明典型用途
app:createdvueAppVue 应用创建初始化第三方库
app:beforeMountvueApp应用挂载前最后的配置修改
app:mountedvueApp应用挂载后(仅客户端)启动客户端逻辑
app:errorerror应用错误错误上报
page:start-页面加载开始显示加载条
page:finish-页面加载完成隐藏加载条
page:rendered-页面渲染完成(SSR)SSR 日志
vue:errorerror, instance, infoVue 错误错误上报
link:prefetchto链接预取自定义预取策略

取消监听

ts
// nuxtApp.hook 返回取消函数
const unsubscribe = nuxtApp.hook('page:start', () => {
  // ...
})

// 不再需要时取消
unsubscribe()

TIP

大多数情况下不需要手动取消 但如果钩子注册在条件语句中或需要动态切换,取消监听可以避免内存泄漏

Nuxt Hooks

在构建时运行,主要用于模块开发和 nuxt.config.ts 中。

在 nuxt.config.ts 中使用

ts
export default defineNuxtConfig({
  hooks: {
    'pages:extend'(pages) {
      // 动态添加页面
      pages.push({
        name: 'custom',
        path: '/custom',
        file: '~/app/pages/custom.vue',
      })
    },

    'components:extend'(components) {
      // 修改组件列表
    },
  },
})

在模块中使用

ts
export default defineNuxtModule({
  setup(options, nuxt) {
    nuxt.hook('ready', () => {
      console.log('Nuxt ready')
    })

    nuxt.hook('build:before', () => {
      console.log('构建前')
    })
  },
})

实用示例:动态添加后台管理页面

ts
export default defineNuxtConfig({
  hooks: {
    'pages:extend'(pages) {
      // 根据环境变量决定是否添加管理页面
      if (process.env.ENABLE_ADMIN === 'true') {
        pages.push({
          name: 'admin-dashboard',
          path: '/admin',
          file: '~/app/pages/admin/index.vue',
        })
      }
    },
  },
})

常用 Nuxt Hooks

钩子说明典型用途
readyNuxt 就绪初始化逻辑
build:before构建前修改构建配置
build:done构建完成生成额外文件
pages:extend扩展页面动态添加/移除页面
components:extend扩展组件动态添加组件
imports:extend扩展自动导入添加自定义自动导入
imports:dirs添加自动导入目录模块注册组合式函数
nitro:configNitro 配置修改服务端配置

Nitro Hooks

在服务端运行,用于请求处理和服务端事件。

在服务端插件中使用

ts
export default defineNitroPlugin((nitroApp) => {
  // 请求钩子
  nitroApp.hooks.hook('request', (event) => {
    console.log('请求:', event.path)
  })

  // 响应钩子
  nitroApp.hooks.hook('afterResponse', (event) => {
    console.log('响应:', event.path, event.node.res.statusCode)
  })

  // 错误钩子
  nitroApp.hooks.hook('error', async (error, event) => {
    console.error('服务端错误:', error)
  })

  // 关闭钩子
  nitroApp.hooks.hook('close', () => {
    console.log('服务器关闭')
  })
})

实用示例:请求日志中间件

ts
export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('request', (event) => {
    const start = Date.now()
    event.context.startTime = start
  })

  nitroApp.hooks.hook('afterResponse', (event) => {
    const duration = Date.now() - event.context.startTime
    console.log(`${event.method} ${event.path} → ${duration}ms`)
  })
})

常用 Nitro Hooks

钩子说明典型用途
request请求到达日志、鉴权
beforeResponse响应前修改响应数据
afterResponse响应后日志、统计
error错误发生错误上报
close服务器关闭清理资源

钩子执行时序

INFO

理解钩子的触发顺序对调试很重要 以下是一个典型的页面加载流程

text
1. Nuxt Hooks:ready          ← 构建时
2. Nuxt Hooks:build:before   ← 构建时
3. Nuxt Hooks:build:done     ← 构建时
4. ─── 运行时 ───
5. Nitro Hooks:request       ← 服务端请求到达
6. App Hooks:app:created     ← Vue 应用创建
7. App Hooks:page:start      ← 页面加载开始
8. App Hooks:page:rendered   ← SSR 渲染完成
9. Nitro Hooks:afterResponse ← 服务端响应
10. App Hooks:app:beforeMount ← 客户端挂载前
11. App Hooks:app:mounted     ← 客户端挂载后
12. App Hooks:page:finish     ← 页面加载完成

常见问题

问题原因解决方案
钩子不触发注册时机不对App Hooks 在插件中注册,Nuxt Hooks 在模块/配置中注册
app:mounted 在 SSR 时不触发该钩子只在客户端触发SSR 需要的逻辑用 page:rendered
钩子中异步操作报错忘记 async/await确保异步钩子回调标记为 async
错误钩子中再次抛出错误导致无限循环错误钩子中只做日志/上报,不要 throw

基于 Nuxt 4 官方文档整理编写