
Nuxt 预渲染完全指南nuxt generate 爬虫机制、选择性预渲染与 _payload.json 数据复用【免费下载链接】nuxtthe full-stack Vue framework项目地址: https://gitcode.com/GitHub_Trending/nu/nuxtNuxt 支持将站点中的部分页面在构建时静态渲染Prerendering请求发生时直接返回预构建好的 HTML 而非实时生成从而改善首屏性能与 SEO 指标。本文以 Nuxt 官方文档docs/1.getting-started/15.prerendering.md为主体结合当前仓库中的源码实现完整覆盖nuxt generate爬虫式预渲染机制、选择性预渲染配置、experimental.payloadExtraction载荷提取以及prerenderRoutes、prerender:routes、prerender:generate三个运行时预渲染钩子的用法与底层原理帮助你在真实项目中落地构建时渲染与混合渲染Hybrid方案。一、爬虫式预渲染Crawl-based Pre-renderingNuxt 允许你在构建阶段渲染应用中选定的页面。当有请求到来时Nuxt 直接提供这些预构建好的页面而不是即时生成。关于各种渲染模式的完整对比可参考 Nuxt 渲染模式。1.1 使用nuxt generate命令使用nuxt generate命令 配合 Nitro 爬虫来构建并预渲染你的应用。该命令等价于将nitro.static选项设为true后执行nuxt build也等价于运行nuxt build --prerendernpx nuxt generateyarn nuxt generatepnpm nuxt generatebun x nuxt generatedeno x nuxt generate执行后你可以将.output/public目录部署到任意静态托管服务或在本地用npx serve .output/public预览效果。静态与预渲染构建还会额外输出200.html和404.html这两个 SPA 回退文件。它们的作用可参考 什么是 200.html 与 404.html 中的说明静态托管平台在找不到精确匹配的路径文件时会按平台约定回退到这两个文件从而让 Vue Router 接管客户端路由保证 SPA 式深链接体验。1.2 Nitro 爬虫的工作原理理解爬虫机制对正确配置预渲染至关重要。Nitro 爬虫按以下流程工作加载应用根路由/的 HTML以及~/pages目录中所有非动态页面外加nitro.prerender.routes数组中声明的其他路由。将 HTML 与_payload.json保存到~/.output/public/目录以便后续静态分发。在 HTML 中找出所有锚点标签a href...作为下一步要访问的路由。对每个新发现的锚点重复步骤 1–3直到没有更多可爬取的锚点为止。这一机制的含义是没有被任何可发现页面链接到的页面无法被自动预渲染。因此对于动态数据驱动的页面需要后文介绍的选择性预渲染或运行时注册机制。二、选择性预渲染Selective Pre-rendering你可以手动指定 Nitro 在构建时抓取并预渲染的路由也可以忽略不希望预渲染的路由。2.1nitro.prerender.routes与ignore在nuxt.config.ts中export default defineNuxtConfig({ nitro: { prerender: { routes: [/user/1, /user/2], ignore: [/dynamic], }, }, })routes强制纳入预渲染队列的路由列表无论爬虫是否从锚点中发现它们ignore从预渲染队列中排除的路由。2.2 结合crawlLinks预渲染爬虫无法发现的路由某些路由如/sitemap.xml、/robots.txt不会以锚点形式出现在任何页面的 HTML 中爬虫自然无法发现。此时可以开启crawlLinks并显式声明这些路由export default defineNuxtConfig({ nitro: { prerender: { crawlLinks: true, routes: [/sitemap.xml, /robots.txt], }, }, })把nitro.prerender直接设为true其效果相当于把nitro.prerender.crawlLinks设为true。从源码结构看crawlLinks这一配置直接决定了 pages 模块的预渲染服务器插件如何筛选路由。prerender.server.ts 在预渲染阶段遍历#build/routes中的全部路由记录其筛选逻辑为function shouldPrerender (path: string) { return crawlLinks || !!routeRulesMatcher(path).prerender }即一条 pages 路由会被自动加入预渲染队列当且仅当crawlLinks为真或该路径命中的routeRules显式声明了prerender: true。同时该插件会跳过路径中包含:的动态路由if (route.path.includes(:))但对可选动态段与 catch-all 路由的根路径如/:slug?对应的/仍会注册预渲染——这解释了为什么「非动态页面」会在第 1.2 节步骤 1 中被自动预渲染而纯动态页面不会。2.3 通过routeRules配置更灵活的方式是在routeRules中按路由模式声明支持 glob 通配export default defineNuxtConfig({ routeRules: { // 设为 true 表示该路由需要预渲染 /rss.xml: { prerender: true }, // 设为 false 表示跳过预渲染 /this-DOES-NOT-get-prerendered: { prerender: false }, // /blog 下所有路由只要被其他页面链接到就会被预渲染 /blog/**: { prerender: true }, }, })prerender: true与prerender: false分别表示「纳入预渲染」和「跳过预渲染」glob 模式如/blog/**使其适用于一整个栏目。2.4 页面文件内的defineRouteRules简写作为简写方式你也可以直接在页面组件中用defineRouteRules声明script setup // 或者在页面级别设置 defineRouteRules({ prerender: true, }) /script template div h1Homepage/h1 pPre-rendered at build time/p /div /template它会等价于如下nuxt.config.ts配置export default defineNuxtConfig({ routeRules: { /: { prerender: true }, }, })需要注意该写法是实验性功能使用前必须在nuxt.config中启用experimental.inlineRouteRules选项更多背景可参考 实验性功能 文档。三、载荷提取Payload Extraction当 Nuxt 在服务端渲染页面时会把数据获取的结果useAsyncData与useFetch以及应用状态useState序列化进 payload使客户端无需重新请求即可直接水合hydrate。开启载荷提取后Nuxt 还会把这份 payload 额外写成与路由 HTML 并排的_payload.json文件预渲染路由在构建时生成对应的 payload 文件使用 ISR 或 SWR 缓存 的路由在首次被渲染时生成 payload 文件——即使站点并非纯静态。客户端导航发生时Nuxt 会拉取目标路由的_payload.json直接复用其中提取的数据而不是在浏览器里重新执行数据获取。该行为由experimental.payloadExtraction选项控制取值初始渲染客户端导航特点clientpayload 内联在 HTML 中从_payload.json提取首次加载无额外网络请求true默认提取到独立的_payload.json从_payload.json提取HTML 更小、payload 文件可被 CDN 缓存代价是首次加载多一次请求false始终内联在 HTML 中无 payload 文件完全不生成_payload.json默认值为true当设置compatibilityVersion: 5时默认为client当ssr: false时被强制为false。export default defineNuxtConfig({ experimental: { payloadExtraction: client, }, })3.1 源码层面的默认值推导上述默认值逻辑在 experimental.ts 中通过$resolve钩子实现可以确认与文档完全一致payloadExtraction: { $resolve: async (val, get) { if ((await get(ssr)) false) { return false } if (val client || typeof val boolean) { return val } return (await get(future.compatibilityVersion)) 5 ? client as const : true }, },另外experimental.payloadExtraction最终生效与否还依赖构建上下文templates.ts 在生成#build/nuxt.config.mjs时推导该标志只有当 Nitro 为静态构建、存在 ISR/cache路由规则、nitro.prerender.routes非空、或routeRules中存在prerender规则时写入构建产物的payloadExtraction才为true。而在 nuxt.ts 中当该选项开启时Nuxt 会追加payload.client插件仅在启用 pages 时负责客户端导航期间加载_payload.json。3.2 几个需要留意的实际影响纯静态站点上数据可能过期客户端导航复用的是构建时抓取的数据在下一次重建之前数据不会更新。ISR/SWR 路由可与 CDN 协同CDN 可以像缓存 HTML 一样缓存 payload 文件提升已缓存路由的客户端导航性能。动态路由如pages/[...slug].vue可以用 glob 模式加入例如/**: { isr: true }。自定义类型的序列化限制payload 使用 devalue 进行序列化自定义类型如 class 实例需要通过 payload 插件提供自定义的 reducer 与 reviver 才能在往返序列化后存活。相关机制参见 useNuxtApp 的 payload 文档。四、运行时预渲染配置Runtime Prerender Configuration除了构建前静态声明路由Nuxt 还允许在预渲染执行过程中动态注册路由或干预每条路由的生成。4.1prerenderRoutes组合式函数你可以在 Nuxt 上下文的运行时调用prerenderRoutes向 Nitro 追加需要预渲染的路由。例如在页面中被预渲染时把相关详情页也注册进队列script setup prerenderRoutes([/some/other/url]) prerenderRoutes(/api/content/article/my-article) /script template div h1This will register other routes for prerendering when prerendered/h1 /div /template从源码看ssr.ts 中的实现非常轻量export function prerenderRoutes (path: string | string[]): void { if (!import.meta.server || !import.meta.prerender) { return } const paths toArray(path) useRequestEvent()?.res.headers.append(x-nitro-prerender, paths.map(p encodeURIComponent(p)).join(, )) }它只在import.meta.server import.meta.prerender同时成立时生效实现方式是向当前响应的x-nitro-prerender头追加编码后的路径——Nitro 爬虫读取该头后便知道要接着预渲染哪些路由。这意味着该函数在普通 SSR 请求中是空操作不会产生任何副作用因此可以放心地写在共享代码路径中。4.2prerender:routesNuxt 钩子该钩子在预渲染开始前被调用适合从外部数据源如 CMS批量注册路由export default defineNuxtConfig({ hooks: { async prerender:routes (ctx) { const { pages } await fetch(https://api.some-cms.com/pages).then( res res.json(), ) for (const page of pages) { ctx.routes.add(/${page.name}) } }, }, })4.3prerender:generateNitro 钩子该钩子在预渲染过程中对每一条路由被调用适合做逐条路由的精细处理比如跳过包含敏感信息的私有页面export default defineNuxtConfig({ nitro: { hooks: { prerender:generate (route) { if (route.route?.includes(private)) { route.skip true } }, }, }, })五、小结预渲染方案选型速查场景推荐方式整个站点静态化部署nuxt generate等价nitro.static: true直接部署.output/public爬虫无法发现的资源sitemap、robots、API 内容nitro.prerender.routescrawlLinks或routeRules中prerender: true明确不想预渲染的路由nitro.prerender.ignore或routeRules中prerender: false整栏目glob预渲染routeRules的/blog/**模式路由集合来自 CMS 等外部数据prerender:routes钩子渲染页面时发现新的关联路由页面内调用prerenderRoutes()逐条路由的跳过/干预逻辑nitro.hooks的prerender:generate客户端导航免重新请求数据默认开启的 payload 提取按站点形态选择experimental.payloadExtraction的client/true/false核心认知只有一条爬虫只能沿锚点发现页面凡「链接不到的页面」都必须通过上述静态配置或运行时机制显式纳入预渲染队列而_payload.json机制则决定了预渲染收益能否延伸到客户端导航——两者配合才是完整的 Nuxt 预渲染实践。【免费下载链接】nuxtthe full-stack Vue framework项目地址: https://gitcode.com/GitHub_Trending/nu/nuxt创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考