拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Nuxt Kit 服务端扩展完全指南:使用 Nitro 工具 API 添加 Handler、插件与预渲染路由

Nuxt Kit 服务端扩展完全指南使用 Nitro 工具 API 添加 Handler、插件与预渲染路由【免费下载链接】nuxtthe full-stack Vue framework项目地址: https://gitcode.com/GitHub_Trending/nu/nuxtNitro 是 Nuxt 的默认服务端引擎。本文基于 nuxt/kit 面向模块作者暴露的 9 个 Nitro 工具函数展开系统讲解addServerHandler、addDevServerHandler、useNitro/tryUseNitro、addServerPlugin、addPrerenderRoutes以及三组服务端自动导入 API并深入到 nitro.ts 的底层实现与 nuxt/nitro-server 的接入点帮助你掌握如何在 Nuxt 模块中注册服务端路由、中间件、扩展运行时行为并管理预渲染清单。读完本文你将具备编写可复用的服务端增强模块所需的全部 API 知识。Nitro 与 Nuxt Kit 的关系Nitro 是一个开源的 TypeScript 服务端框架用于构建高性能 Web 服务器Nuxt 将其作为服务端引擎使用。在模块开发场景中Nuxt Kit 提供了与 Nitro 打交道的官方通道所有注册动作最终都落到 Nuxt 实例的配置项与钩子上。从源码结构看这些工具分为几类实例访问useNitro/tryUseNitro获取正在运行的 Nitro 实例处理器注册addServerHandler/addDevServerHandler向 Nitro 增加路由与中间件运行时扩展addServerPlugin注入 Nitro 插件预渲染管理addPrerenderRoutes追加需要静态生成的动态路由服务端自动导入addServerImports/addServerImportsDir/addServerScanDir。它们的实现集中在 packages/kit/src/nitro.ts类型定义则内联在 packages/kit/src/nitro-types.ts 中——之所以内联而不是直接引用nitropack/nitro是为了让nuxt/kit不依赖任一 Nitro 包即可编译从而接受同一份注册结构而无论宿主 Nuxt 实际提供哪个 Nitro 主版本。addServerHandler注册生产环境处理器addServerHandler用于新增一个 Nitro 服务端处理器是模块创建自定义 API 路由或中间件的核心入口。基础用法import { addServerHandler, createResolver, defineNuxtModule } from nuxt/kit export default defineNuxtModule({ setup (options) { const { resolve } createResolver(import.meta.url) addServerHandler({ route: /robots.txt, handler: resolve(./runtime/robots.get), }) }, })配套的运行时处理文件robots.get.ts中.get后缀即代表GET方法import { defineEventHandler } from nitro/h3 export default defineEventHandler(() { return { body: User-agent: *\nDisallow: /, } })访问/robots.txt时返回User-agent: * Disallow: /函数签名与参数说明function addServerHandler (handler: NitroEventHandler): voidhandler为处理器对象属性如下属性类型必填说明handlerstringtrue事件处理器的文件路径相对路径会在模块内用createResolver().resolve()解析为绝对路径。routestringfalse路径前缀或具体路由。若传入空字符串则该处理器作为中间件使用对所有请求生效。middlewarebooleanfalse标记为中间件处理器。中间件会在每个路由前被调用通常应不返回任何内容以便把控制权交给后续处理器。lazybooleanfalse使用懒加载导入处理器仅在首次被请求时才加载适合不常访问的路由。methodstringfalse路由方法匹配器。若处理文件名中已包含方法名如robots.get该值会被自动用作默认值。从源码理解方法推断与存储位置addServerHandler的实现揭示了两个值得注意的细节packages/kit/src/nitro.ts#L117-L129方法从文件名推断normalizeHandlerMethod用正则/(\.(get|head|patch|post|put|delete|connect|options|trace)(\.\w)*)$/从处理文件路径中提取方法并转大写。也就是说文件命名为hello.post.ts等价于显式传入method: POST。入队配置而非立即生效注册结果被push进nuxt.options.serverHandlers数组该数组默认值为[]见 packages/schema/src/config/nitro.ts#L65。Nitro 真正读取这些处理器是在后续的nitro:config/nitro:init阶段。addDevServerHandler仅开发环境可见的处理器addDevServerHandler添加只在开发模式下使用的服务器处理器它不会进入生产构建产物适合注册 Tailwind 配置查看器等仅在本地调试时需要的工具。用法与签名import { defineEventHandler } from nitro/h3 import { addDevServerHandler, createResolver, defineNuxtModule } from nuxt/kit export default defineNuxtModule({ setup () { addDevServerHandler({ handler: defineEventHandler(() { return { body: Response generated at ${new Date().toISOString()}, } }), route: /_handler, }) }, })函数签名function addDevServerHandler (handler: NitroDevEventHandler): void参数表属性类型必填说明handlerEventHandlertrue事件处理器函数对象开发模式下直接内联无需文件路径。routestringfalse路径前缀或路由。传入空字符串则作为中间件。实战案例内嵌 Tailwind 配置查看器文档给出的经典场景是给模块挂一个 Tailwind 配置查看器注意它借助nuxt.options.app?.baseURL把路由放在应用基路径下避免与部署前缀冲突import { joinURL } from ufo import { addDevServerHandler, defineNuxtModule } from nuxt/kit export default defineNuxtModule({ async setup (options, nuxt) { const route joinURL(nuxt.options.app?.baseURL, /_tailwind) // ts-expect-error - tailwind-config-viewer does not have correct types const createServer await import(tailwind-config-viewer/server/index.js).then(r r.default || r) as any const viewerDevMiddleware createServer({ tailwindConfigProvider: () options, routerPrefix: route }).asMiddleware() addDevServerHandler({ route, handler: viewerDevMiddleware }) }, })在源码实现中addDevServerHandler会把处理器追加到nuxt.options.devServerHandlers默认[]见 packages/schema/src/config/nitro.ts#L66到 Nitro 初始化阶段这些开发处理器被合并进nitro.options.devHandlerspackages/nitro-server/src/index.ts#L968因此天然与生产 handler 分流。useNitro 与 tryUseNitro访问 Nitro 实例useNitro()返回当前 Nitro 实例类型为Nitro。注意它有两条使用约束警告只能在ready钩子触发后才能调用useNitro()。注意对 Nitro 实例配置的修改不会生效实例已定型应通过配置钩子去改。标准用法import { defineNuxtModule, useNitro } from nuxt/kit export default defineNuxtModule({ setup (options, nuxt) { const resolver createResolver(import.meta.url) nuxt.hook(ready, () { const nitro useNitro() // Do something with Nitro instance }) }, })function useNitro (): NitrotryUseNitro无服务端场景的安全版本tryUseNitro()在存在 Nitro 实例时返回它否则返回undefined。在ready钩子运行之前没有 Nitro 实例而当配置的server.builder不使用 Nitro 时例如输出纯客户端 SPA 的构建器整个生命周期内都不存在实例。凡是没有服务器也应该正常工作的逻辑都应优先使用它因为此时服务端路由、路由规则和预渲染都是缺失的。import { defineNuxtModule, tryUseNitro } from nuxt/kit export default defineNuxtModule({ setup (options, nuxt) { nuxt.hook(ready, () { const nitro tryUseNitro() if (!nitro) { // no server: skip anything that would only run there return } }) }, })function tryUseNitro (): Nitro | undefinedserver.builder的取值解析位于 packages/schema/src/config/nitro.ts#L12-L24字符串nitro与vite分别映射到nuxt/nitro-server与nuxt/vite-server这两个包名也可传入实现了bundle方法的对象。底层实现上useNitro()只是对tryUseNitro()判空后的包装packages/kit/src/nitro.ts#L212-L218而tryUseNitro()返回的是nuxt._nitro属性packages/kit/src/nitro.ts#L228-L230。这个属性由 nuxt/nitro-server 在调用createNitro(nitroConfig)创建出 Nitro 实例后写入随后触发nitro:init钩子供模块消费。addServerPlugin扩展 Nitro 运行时行为addServerPlugin用于给 Nitro 添加插件从而在请求生命周期中注入自定义逻辑如日志、鉴权、请求改写。使用要点提示Nitro 插件机制的进一步说明可参考 Nitro 官方文档的 Plugins 章节。警告插件文件内必须显式从nitro导入definePluginuseRuntimeConfig等同理——这些不会自动注入。用法与签名import { addServerPlugin, createResolver, defineNuxtModule } from nuxt/kit export default defineNuxtModule({ setup () { const { resolve } createResolver(import.meta.url) addServerPlugin(resolve(./runtime/plugin.ts)) }, })function addServerPlugin (plugin: string): void属性类型必填说明pluginstringtrue插件文件路径。插件必须默认导出一个接收 Nitro 实例作为参数的函数。模块与运行时插件示例模块侧注册import { addServerPlugin, createResolver, defineNuxtModule } from nuxt/kit export default defineNuxtModule({ setup () { const { resolve } createResolver(import.meta.url) addServerPlugin(resolve(./runtime/plugin.ts)) }, })运行时插件监听request/response钩子import { definePlugin } from nitro export default definePlugin((nitroApp) { nitroApp.hooks.hook(request, (event) { console.log(on request, event.req.url) }) nitroApp.hooks.hook(response, async (res) { console.log(on response, await res.text()) }) })底层看addServerPlugin会将插件路径规范化后 push 进nuxt.options.nitro.pluginspackages/kit/src/nitro.ts#L151-L179该配置最终会通过nitro:config钩子被 Nitro 读取。addPrerenderRoutes补充预渲染路由addPrerenderRoutes向 Nitro 追加需要预渲染的路由适合让模块在静态生成阶段把那些无法从页面扫描得到的动态 URL例如站点地图、文章详情页写入产物。用法与签名import { addPrerenderRoutes, defineNuxtModule } from nuxt/kit export default defineNuxtModule({ meta: { name: nuxt-sitemap, configKey: sitemap, }, defaults: { sitemapUrl: /sitemap.xml, prerender: true, }, setup (options) { if (options.prerender) { addPrerenderRoutes(options.sitemapUrl) } }, })function addPrerenderRoutes (routes: string | string[]): void属性类型必填说明routesstring \| string[]{langts}true要预渲染的一个或一组路由。实现上addPrerenderRoutes先过滤空值再通过nuxt.hook(prerender:routes, ...)把路由加入ctx.routesSetpackages/kit/src/nitro.ts#L184-L196。而 Nitro 侧的prerender:routes事件会被转发为 Nuxt 钩子packages/nitro-server/src/index.ts#L936-L938从而形成模块注册 → Nitro 触发 → Nuxt 收集的闭环。addServerImports为服务端声明自动导入addServerImports把指定的具名导出注册到 Nitro 的自动导入清单中让这些函数在服务端代码里无需手动import即可使用。用法与签名import { addServerImports, createResolver, defineNuxtModule } from nuxt/kit export default defineNuxtModule({ setup (options) { const names [ useStoryblok, useStoryblokApi, useStoryblokBridge, renderRichText, RichTextSchema, ] names.forEach(name addServerImports({ name, as: name, from: storyblok/vue }), ) }, })function addServerImports (dirs: NuxtImport | NuxtImport[]): voidimports可以是一个或一组对象属性如下属性类型必填说明namestringtrue待识别的导入名称。fromstringtrue模块标识符即从哪个包导入。prioritynumberfalse导入优先级多个同名导入时优先使用优先级最高的。disabledbooleanfalse是否停用该导入。metaRecordstring, anyfalse导入的元数据。typebooleanfalse是否为纯类型导入。typeFromstringfalse生成类型声明时作为from使用的值。asstringfalse导入后使用的别名。客户端/服务端通用的类型注意事项警告若希望提供在服务端与客户端都可使用、并且能被shared/目录消费的工具函数则必须让addImports与addServerImports从同一个源文件导入该函数且签名完全一致。该源文件不应导入任何上下文相关的模块如 Nitro 上下文、Nuxt App 上下文否则类型检查阶段可能报错。从实现看addServerImports并不会立刻改动什么而是注册到nitro:config钩子中最终把导入对象 push 进config.imports.imports数组packages/kit/src/nitro.ts#L253-L266。addServerImportsDir扫描目录注册自动导入addServerImportsDir注册一个目录让 Nitro 扫描其中导出的函数并自动导入到服务端。用法与签名import { addServerImportsDir, createResolver, defineNuxtModule } from nuxt/kit export default defineNuxtModule({ meta: { name: my-module, configKey: myModule, }, setup (options) { const { resolve } createResolver(import.meta.url) addServerImportsDir(resolve(./runtime/server/composables)) }, })function addServerImportsDir (dirs: string | string[], opts: { prepend?: boolean }): void属性类型必填说明dirsstring \| string[]{langts}true要注册给 Nitro 扫描的一个或一组目录。opts{ prepend?: boolean }false若prepend为true目录会被插入扫描列表头部影响同名函数优先级。完整示例模块注册目录import { addServerImportsDir, createResolver, defineNuxtModule } from nuxt/kit export default defineNuxtModule({ meta: { name: my-module, configKey: myModule, }, setup (options) { const { resolve } createResolver(import.meta.url) addServerImportsDir(resolve(./runtime/server/composables)) }, })被扫描目录中导出组合式函数export function useApiSecret () { const { apiSecret } useRuntimeConfig() return apiSecret }随后即可在任意服务端代码中直接调用import { defineEventHandler } from nitro/h3 export default defineEventHandler(() { const apiSecret useApiSecret() // Do something with the apiSecret })底层实现中注册发生在nitro:config钩子内把目录写入config.imports.dirsopts.prepend决定使用unshift还是pushpackages/kit/src/nitro.ts#L271-L282。addServerScanDir模拟~/server的完整目录语义addServerScanDir与上面两个只做自动导入的 API 不同它注册的目录会被 Nitro当作~~/server目录一样扫描其子目录即其中的api、routes、middleware、utils子目录分别按对应语义生效。注意仅~~/server/api、~~/server/routes、~~/server/middleware与~~/server/utils会被扫描。用法与签名import { addServerScanDir, createResolver, defineNuxtModule } from nuxt/kit export default defineNuxtModule({ meta: { name: my-module, configKey: myModule, }, setup (options) { const { resolve } createResolver(import.meta.url) addServerScanDir(resolve(./runtime/server)) }, })function addServerScanDir (dirs: string | string[], opts: { prepend?: boolean }): void属性类型必填说明dirsstring \| string[]{langts}true要注册为 Nitro 服务端目录的一个或一组目录。opts{ prepend?: boolean }false若prepend为true目录插入扫描列表开头。完整示例模块注册一个带utils子目录的服务端目录import { addServerScanDir, createResolver, defineNuxtModule } from nuxt/kit export default defineNuxtModule({ meta: { name: my-module, configKey: myModule, }, setup (options) { const { resolve } createResolver(import.meta.url) addServerScanDir(resolve(./runtime/server)) }, })目录内提供工具函数export function hello () { return Hello from server utils! }随后在服务端 API 中直接调用import { defineEventHandler } from nitro/h3 export default defineEventHandler(() { return hello() // Hello from server utils! })实现上目录被写入config.scanDirs同样在nitro:config钩子中见 packages/kit/src/nitro.ts#L288-L297Nitro 会把runtime/server/api下的文件注册为API路由、runtime/server/middleware下的注册为中间件从而实现模块自带一套迷你server目录的效果。版本感知注册面向 Nitro v2 / v3 的兼容层本仓库的 Kit 实现比文档表格更进一步地支持了版本化注册。在 packages/kit/src/nitro-types.ts 中NitroEventHandler区分NitroEventHandlerV2与NitroEventHandlerV3两套结构v2 由route 可选method组成v3 则把route变为必填并要求使用如/api/:id、/blog/**的 HTTP pathname 模式还额外支持QUERY方法与format: web | node、env等字段。Kit 的入口函数为同一套 API 提供了三种重载直接传 v2 对象、用{ version: 3 }选项标记 v3 对象或传{ 2: ..., 3: ... }的版本映射结构见 packages/kit/src/nitro.ts#L117-L129。resolveVersionedRegistration会根据宿主 Nitro 主版本挑选匹配变体在 v3 宿主上仅 v2 的注册仍会被保留并在运行时做兼容包装而仅 v3 的注册在 v2 宿主上会被跳过并通过诊断记录NUXT_B8024packages/kit/src/nitro.ts#L41-L46。这套机制让同一份模块代码可以平滑兼容新旧两代 Nitro是文档示例之外的进阶能力。小结与实战建议本文围绕 docs/4.api/5.kit/12.nitro.md 拆解了 Nuxt Kit 的全部 Nitro 工具它们都遵循模块注册到 Nuxt 配置 →nitro:config钩子汇聚 → Nitro 引擎消费的统一流程。实际选型时可参考以下准则路由与中间件生产环境用addServerHandler推荐文件命名xxx.get.ts以省去method仅调试用addDevServerHandler运行时钩子请求/响应处理用addServerPlugin注意在插件内显式导入definePlugin与useRuntimeConfig静态站点补充 URL用addPrerenderRoutes工具函数自动导入目录整体交给addServerImportsDir需要同时支持shared/场景的少量函数用addServerImports要获得完整api/routes/middleware/utils语义则用addServerScanDir实例访问优先tryUseNitro()以兼容无服务端的 SPA 构建器并在ready钩子之后调用若同时面向 Nitro v2/v3 生态善用版本映射重载。【免费下载链接】nuxtthe full-stack Vue framework项目地址: https://gitcode.com/GitHub_Trending/nu/nuxt创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门