ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Nuxt 生命周期 Hooks 全解析:App 运行时、构建期与 Nitro 服务端三大 Hook 体系详解

Nuxt 生命周期 Hooks 全解析:App 运行时、构建期与 Nitro 服务端三大 Hook 体系详解 Nuxt 生命周期 Hooks 全解析App 运行时、构建期与 Nitro 服务端三大 Hook 体系详解【免费下载链接】nuxtthe full-stack Vue framework项目地址: https://gitcode.com/GitHub_Trending/nu/nuxtNuxt 内置了一套强大的 Hooks钩子系统允许开发者在应用的几乎每一个生命周期节点上注入自定义逻辑——从 Vue 应用创建、页面渲染到模块安装、路由扫描、构建打包乃至 Nitro 服务端的每一次请求与响应。本篇文章以 Nuxt API 文档中 Lifecycle Hooks 为核心系统梳理运行时 App Hooks、构建期 Nuxt Hooks、服务端 Nitro App Hooks 三张完整清单并结合本仓库源码说明每个 Hook 的触发时机、参数含义与典型使用场景。阅读完成后你将能够在插件、模块与服务端插件中准确选择并注册合适的 Hook也能基于 TypeScript 类型扩展属于自己的自定义 Hook。一、Hook 体系总览三类 Hooks 各管一段生命周期Nuxt 的 Hooks 系统按运行阶段被划分为三类对应三种不同的注册入口与监听环境Hook 类别触发阶段典型注册位置监听环境App Hooks运行时Vue 应用创建、挂载、页面切换、错误上报等客户端/服务端渲染过程Nuxt 插件app/pluginsServer Client或仅其一Nuxt Hooks构建期Nuxt 实例初始化、模块安装、路由与组件扫描、Vite/webpack 构建等nuxt.config.ts的hooks字段、Nuxt 模块的setup构建时/开发服务器Nitro App Hooks运行时服务端Nitro 请求处理、HTML 渲染、错误处理等服务器运行时服务端插件server/pluginsServer从源码结构看整套系统建立在 unjs/hookable构建期的全部 Hook 名称与签名被集中定义在NuxtHooks接口中见 packages/schema/src/types/hooks.ts。因此无论是nuxtApp.hook()还是nuxt.hook()最终都只是向同一个 hookable 实例注册回调而已。更完整的概念背景含各分类的实际代码示例可以参考 Nuxt Hooks 指南下文则聚焦 API 参考级别的完整 Hook 清单。二、App Hooks运行时在应用渲染生命周期上挂钩App Hooks 作用于 Nuxt 运行时Runtime主要通过 Nuxt 插件即 app 目录下的 plugins注册也可以在 Vue 组合式函数中调用。插件的setup函数会拿到nuxtApp实例通过nuxtApp.hook()即可监听对应事件export default defineNuxtPlugin((nuxtApp) { nuxtApp.hook(page:start, () { /* your code goes here */ }) })除了命令式注册插件还可以直接以对象形式携带hooks字段此时需要启用插件元信息在 packages/nuxt/src/app/nuxt.ts 中可以看到registerPluginHooks会将这些plugin.hooks批量写入nuxtApp.hooks.addHooks从而统一进入运行时 Hook 通道。运行时 Hook 的完整类型定义位于 packages/nuxt/src/app/nuxt.ts 的RuntimeNuxtHooks接口其中app:error、app:rendered等来自服务端可寻址的子集NuxtServerRuntimeHooks见 packages/nuxt/src/app/types.ts。全部可用 App Hooks 如下表所示Hook参数环境说明app:createdvueAppServer Client初始vueApp实例创建时调用。app:errorerrServer Client发生致命错误时调用。app:error:cleared{ redirect? }Server Client致命错误被清除时调用。vue:setup-Server ClientNuxt 根组件 setup 初始化时调用。该回调必须为同步函数。vue:errorerr, target, infoServer ClientVue 错误传播到根组件时调用对应 Vue 的onErrorCaptured语义。app:renderedrenderContextServerSSR 渲染完成时调用。app:redirected-ServerSSR 重定向前调用。app:beforeMountvueAppClient应用挂载前调用仅发生在客户端。app:mountedvueAppClientVue 应用在浏览器中初始化并挂载后调用。app:suspense:resolveappComponentClientSuspense解析完成事件触发时调用。app:manifest:update{ id, timestamp }Client检测到应用有新版本可用时调用。app:data:refreshkeys?Client调用refreshNuxtData时触发。link:prefetchtoClientNuxtLink被观测到即将预取时调用。page:startpageComponent?ClientNuxtPage内部Suspense进入 pending 状态时调用。page:finishpageComponent?ClientNuxtPage内部Suspense解析完成resolved时调用。page:loading:start-Client路由导航开始解析前或页面key变化时调用若页面被复用例如在definePageMeta中使用静态key可能不会重新执行页面组件的setup()。page:loading:end-Clientpage:finish之后调用。page:transition:finishpageComponent?Client页面过渡的onAfterLeave事件之后调用。dev:ssr-logslogsClient携带一组由服务端传递到客户端在启用features.devLogs时的服务端日志调用。page:view-transition:starttransitionClient启用实验性 View Transitions 支持见 Transitions 指南后document.startViewTransition被调用时触发transition参数是带types属性ViewTransitionTypeSet可读取或修改的ViewTransition对象。这些 Hook 的触发点可以在运行时入口代码中得到印证。例如在 packages/nuxt/src/app/entry.ts 中服务端与客户端都会在应用创建时先后调用app:created、app:beforeMount、app:mountedapp:suspense:resolve则在 hydration 计数归零后被触发见 packages/nuxt/src/app/nuxt.ts。而 View Transitions 相关 Hook 的注册位于客户端插件 packages/nuxt/src/app/plugins/view-transitions.client.ts。值得注意的是在服务端nuxtApp.hooks.callHook会被包装为逐 Hook 依次在nuxtApp.runWithContext上下文中执行以保证每个回调都能拿到当前请求的 Nuxt 上下文见 packages/nuxt/src/app/nuxt.ts。这意味着在服务端运行时 Hook 的回调中你可以安全地调用useRequestEvent()等需要上下文辅助函数。三、Nuxt Hooks构建期让模块深入 Nuxt 内部流程Nuxt Hooks 在构建期以及开发服务器运行期间可用主要面向 Nuxt 模块Modules与构建上下文。它们的类型定义集中在 packages/schema/src/types/hooks.ts 的NuxtHooks接口中全部构建期 Hook 如下Hook参数说明kit:compatibilitycompatibility, issues允许扩展兼容性检查。readynuxtNuxt 初始化完成、实例就绪后调用。closenuxtNuxt 实例优雅关闭时调用。restart{ hard?: boolean }被调用于重启当前 Nuxt 实例。modules:before-Nuxt 初始化期间、安装用户模块之前调用。modules:done-Nuxt 初始化期间、安装用户模块之后调用。module:beforemodule每个独立模块 setup 前立即调用。module:donemodule每个独立模块 setup 完成后立即调用并携带耗时信息源码中还包含entryPath与timings字段。app:resolveappapp实例解析完成后调用。app:templatesappNuxtApp生成期间调用允许自定义、修改或向构建目录写入.nuxt新增文件。app:templatesGeneratedapp模板被编译进虚拟文件系统vfs见 .nuxt 目录说明之后调用。build:before-Nuxt bundle 构建器执行前调用。build:done-Nuxt bundle 构建器完成后调用。build:manifestmanifestVite 与 webpack 构建 manifest 时调用允许定制 Nitro 用于在最终 HTML 中渲染script与link标签的 manifest。builder:generateAppoptions生成 app 之前调用。builder:watchevent, path开发模式下构建期 watcher 监测到项目文件/目录变化时调用event为add/addDir/change/unlink/unlinkDir之一。pages:extendpages页面路由从文件系统扫描完成后调用。pages:resolvedpages页面路由补充了扫描元数据后调用。pages:routerOptions{ files: Array{ path: string, optional?: boolean } }解析router.options文件时调用数组中靠后的项会覆盖靠前的项。server:devHandlerhandler开发中间件注册到 Nitro dev server 时调用。imports:sourcespresetssetup 阶段调用允许模块扩展来源sources。imports:extendimportssetup 阶段调用允许模块扩展自动导入项。imports:contextcontextunimport context 创建时调用。imports:dirsdirs允许扩展自动导入的目录。components:dirsdirs在app:resolve内调用允许扩展被扫描以自动导入组件的目录。components:extendcomponents允许扩展新的组件。nitro:confignitroConfig初始化 Nitro 前调用允许定制 Nitro 配置。nitro:initnitroNitro 初始化后调用允许注册 Nitro Hooks 并直接与 Nitro 交互。nitro:build:beforenitro构建 Nitro 实例之前调用。nitro:build:public-assetsnitro复制公共资源之后调用允许在 Nitro 服务器构建前修改公共资源。prerender:routesctx允许扩展将要预渲染的路由。build:errorerror构建期发生错误时调用。prepare:typesoptions在 CLI 写入 TypeScript 配置文件.nuxt/tsconfig.app.json、.nuxt/tsconfig.server.json等与.nuxt/nuxt.d.ts之前调用允许向nuxt.d.ts添加自定义 references 与 declarations或直接修改生成配置中的选项。listenlistenerServer, listenerdev server 加载时调用。schema:extendschemas允许扩展默认 schemas。schema:resolvedschema允许扩展已解析的 schema。schema:beforeWriteschema写入给定 schema 之前调用。schema:written-schema 写入之后调用。vite:extendviteBuildContext允许扩展 Vite 默认上下文。vite:extendConfigviteInlineConfig, env允许扩展 Vite 默认配置。在 Nuxt 5 已废弃Nuxt 5 中该 Hook 作用于共享配置而非分离的 client/server 配置。vite:configResolvedviteInlineConfig, env允许读取已解析的 Vite 配置。在 Nuxt 5 已废弃语义同vite:extendConfig。vite:serverCreatedviteServer, envVite server 创建时调用。vite:compiled-Vite server 编译完成后调用。webpack:configwebpackConfigs配置 webpack 编译器之前调用。webpack:configResolvedwebpackConfigs允许读取已解析的 webpack 配置。webpack:compileoptions编译即将开始时调用。webpack:compiledoptions资源加载完成后调用。webpack:changeshortPathWebpackBar 触发change时调用。webpack:error-WebpackBar 在存在错误的情况下触发done时调用。webpack:done-WebpackBar 触发allDone时调用。webpack:progressstatesArrayWebpackBar 触发progress时调用。从源码看该接口还进一步细化了大量参数结构例如module:done携带的timings: { setup: number }、pages:routerOptions的optional语义标记为 optional 的路由文件只有在基于文件的路由已启用时才生效、以及prepare:types携带的references、declarations、tsConfig、nodeTsConfig、sharedTsConfig等完整 TypeScript 配置对象见 packages/schema/src/types/hooks.ts 与 packages/schema/src/types/hooks.ts 附近的注释。此外仓库中还定义了与 webpack 平行的rspack:config、rspack:compile等 Rspack 系列 Hook见 packages/schema/src/types/hooks.ts可作为参考。3.1 在nuxt.config.ts中注册构建期 Hook 可以直接写在配置文件里适用于全局、不依赖模块实例的场景export default defineNuxtConfig({ hooks: { close: () { }, }, })3.2 在 Nuxt 模块中注册模块是构建期 Hook 最主要的消费方——模块的setup会拿到 Nuxt 实例通过nuxt.hook()订阅任意构建期事件import { defineNuxtModule } from nuxt/kit export default defineNuxtModule({ setup (options, nuxt) { nuxt.hook(close, async () { }) }, })这种模式也是绝大多数第三方 Nuxt 模块扩展路由pages:extend、注入组件components:extend、改写 Vite 配置vite:extend的底层通道。四、Nitro App Hooks运行时服务端介入每一次请求与渲染服务端运行时 Hook 面向 Nitro主要服务于 Nitro 服务端插件见 server 目录中的 server plugins用来挂钩 Nitro 的请求周期与 SSR 渲染过程。官方文档完整清单如下表格中本仓库文档列出的具体参数结构参见相关源码注释Hook参数说明dev:ssr-logs{ path, logs }一个请求周期结束时调用携带一组服务端日志。render:responseresponse, { event }发送响应前调用。render:htmlhtml, { event }构建 HTML 之前调用。render:islandislandResponse, { event, islandContext }构建 island HTML 之前调用。close-Nitro 关闭时调用。errorerror, { event? }发生错误时调用。requestevent收到请求时调用。beforeResponseevent, { body }发送响应前调用。afterResponseevent, { body }发送响应后调用。其中render:html、render:response、render:island等渲染管线 Hook 的实际触发点位于 Nitro SSR 渲染器中。以本仓库为例在 packages/nitro-server/src/runtime/handlers/renderer.ts 中可以看到render:html在常规 SSR 与流式渲染streaming: true两条路径上都被调用见 renderer.ts 中相关调用且流式场景下还额外提供了render:html:chunk与render:html:close这类细粒度 Hook 供监听者修改每个 chunk 或注入收尾内容。在服务端插件中注册这些 Hook 的完整写法如下import { definePlugin } from nitro export default definePlugin((nitroApp) { nitroApp.hooks.hook(render:html, (html, { event }) { console.log(render:html, html) html.bodyAppend.push(hrAppended by custom plugin) }) nitroApp.hooks.hook(render:response, (response, { event }) { console.log(render:response, response) }) })注意这里html.bodyAppend.push(...)之所以可行是因为render:html的参数html是包含headAppend、bodyAppend、bodyPrepend等可写数组的 HTML 上下文对象——这正是文档与源码类型所定义的结构也是服务端插件向最终 HTML 注入脚本/标记的官方姿势之一。五、扩展自定义 Hooks让你的模块/插件拥有类型安全的专属事件除了使用内置 Hooks你还可以通过 TypeScript 模块增强Module Augmentation为 Nuxt 定义自己的 Hooks使nuxt.hook()、nuxtApp.hook()、nitroApp.hooks.hook()在调用自定义事件时也能获得完整的类型提示import type { HookResult } from nuxt/schema declare module #app { interface RuntimeNuxtHooks { your-nuxt-runtime-hook: () HookResult } interface NuxtHooks { your-nuxt-hook: () HookResult } } declare module nitro/types { interface NitroRuntimeHooks { your-nitro-hook: () void } }这段声明分别对应三类 Hook 的类型注册表#app模块中的RuntimeNuxtHooks运行时 App Hooks定义于 packages/nuxt/src/app/nuxt.ts、NuxtHooks构建期 Hooks定义于 packages/schema/src/types/hooks.ts以及nitro/types中的NitroRuntimeHooksNitro 运行时 Hooks。完成扩展后你的模块内就可以nuxt.hook(your-nuxt-hook, ...)、插件内可以nuxtApp.hook(your-nuxt-runtime-hook, ...)服务端插件则可以nitroApp.hooks.hook(your-nitro-hook, ...)与使用内置 Hook 完全一致。六、实战建议与常见坑分清环境再选 Hook操作 DOM、访问window的逻辑应挂在app:mounted、page:finish这类 Client 专属 Hook 上需要在服务端渲染阶段收集数据的逻辑则使用app:rendered。若误在服务端运行的 Hook 中触碰浏览器 API会导致 SSR 阶段崩溃。vue:setup必须同步该 Hook 的回调是同步执行的不要在它内部返回异步任务或await否则会破坏 Nuxt 根组件的初始化时序。服务端 Hook 回调里的上下文在服务端nuxtApp的callHook会逐个在runWithContext中执行回调因此可以在 App Hook 中安全使用依赖 Nuxt 上下文的组合式函数但自己通过callHook发布事件时也最好沿用这一模式参考 packages/nuxt/src/app/nuxt.ts。模块中用nuxt.hook插件中用nuxtApp.hook服务端插件中用nitroApp.hooks.hook三者表面相似实则分属构建期与两个运行时混用会因拿不到对应实例或生命周期已过而导致回调不执行。页面加载进度相关 Hook 的边界情况page:loading:start在页面复用静态key时可能不会伴随页面setup()重跑依赖副作用重置的逻辑请不要只挂在它身上。结合 Nuxt Hooks 指南 的配套示例与上文的完整清单你已具备在插件、模块、服务端插件三个层面精准订阅 Nuxt 生命周期事件的能力也掌握了通过模块增强为整个体系贡献自定义 Hook 的方法。【免费下载链接】nuxtthe full-stack Vue framework项目地址: https://gitcode.com/GitHub_Trending/nu/nuxt创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表