Gatsby 服务端渲染(SSR)完全指南:使用 getServerData 按请求动态渲染页面
Gatsby 服务端渲染SSR完全指南使用 getServerData 按请求动态渲染页面【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby本文是围绕 Gatsby 服务端渲染Server-Side RenderingSSR的实战指南讲解如何通过页面组件导出的getServerData函数让 Gatsby 在用户每次访问页面时动态拉取数据并预渲染 HTML。读完本文你将掌握 SSR 页面的创建方法、getServerData的返回值与context参数语义、它与构建期 GraphQL 查询的协作方式以及 SSR 在gatsby develop/gatsby serve下的底层工作机理能够针对动态个性化、鉴权数据、A/B 测试等场景做出正确的渲染方案选型。SSR 在 Gatsby 渲染选项中的定位Gatsby 自 4.0 起在默认的静态站点生成SSG基础上引入了按页可选的渲染模式Deferred Static GenerationDSG与 Server-Side RenderingSSR。SSR 允许你在用户访问页面的那一刻拉取数据并预渲染页面——服务器在收到 HTTP 请求期间生成完整 HTML 并返回给用户数据获取发生在 Gatsby 数据层之外。概念文档 rendering-options.md 明确指出渲染选项定义的是页面面向用户的 HTML 在哪个阶段生成——构建期SSG / 预渲染、HTTP 请求期间SSR或由浏览器端 JavaScript 完成CSR。SSG 是 Gatsby 的默认模式全部 HTML/CSS/JS 在构建期生成并作为静态资源发布因此访问速度最快DSG 则允许开发者把低流量页面推迟到首次请求时再生成以换取更短的构建时间。虽然官方推荐优先使用 SSG 或 DSG但 SSR 在一些特定场景下不可替代动态个性化根据用户身份、地理位置渲染不同内容鉴权数据需要登录态的私有数据且希望搜索引擎能索引A/B 测试按用户分组动态分配实验版本时效性要求高的内容如用户评论需要发布后立即被搜索引擎收录客户端渲染无法满足。如果你不需要预渲染页面仅在浏览器端拉数据即可则可退而使用 client-only routes客户端专属路由无需引入 SSR 的服务器成本。SSR 的完整 API 细节可参考 Server-Side Rendering API 参考文档。如上图所示SSR 模式下每一次请求都会经过服务器执行渲染逻辑dashboard.js等页面脚本并可能调用第三方 API之后再返回响应——这与 SSG 命中的 CDN 缓存流程有本质区别。前置条件开始之前你需要有一个可运行的 Gatsby 站点。如果还没有可以参照 Quick Start 快速创建一个。实现步骤概览SSR 的使用流程非常精简只有两步在页面组件中添加getServerData函数在getServerData内部请求数据并把结果渲染到页面上。下文以「随机狗图」页面为例数据源为 dog.ceo 公共 API逐步演示。请新建页面文件src/pages/ssr.js。Step 1添加getServerData函数只要在页面组件中导出一个名为getServerData的 async 函数Gatsby 就会自动为该页面选择 SSR 渲染模式。先写一个只含标题的空页面import * as React from react const SSRPage () ( main h1SSR Page with Dogs/h1 /main ) export default SSRPage export async function getServerData() {} // highlight-line仅凭这一行空函数页面就完成了从 SSG 到 SSR 的切换。参考文档强调你只能在页面文件中导出getServerData不能从非页面文件导出它——Gatsby 会扫描页面组件并据此决定渲染模式。Step 2在getServerData中请求数据并展示getServerData内可以执行任意逻辑但必须返回一个包含props的对象。返回的props会被 Gatsby 注入到页面组件上成为名为serverData的 prop——这与页面查询page query自动把结果作为dataprop 传入的机制类似。使用原生fetch从 dog.ceo API 拉取随机狗图// The rest of the page export async function getServerData() { try { const res await fetch(https://dog.ceo/api/breeds/image/random) if (!res.ok) { throw new Error(Response failed) } return { props: await res.json(), } } catch (error) { return { status: 500, headers: {}, props: {} } } }此后用户每次访问该页面服务器都会请求https://dog.ceo/api/breeds/image/random并把响应作为serverData提供给页面组件。该 API 的响应结构为{ message: img-url, status: }。现在把图片渲染出来import * as React from react const SSRPage ({ serverData }) ( // highlight-line main h1SSR Page with Dogs/h1 {/* highlight-next-line */} img altHappy dog src{serverData.message} / /main ) export default SSRPage export async function getServerData() { try { const res await fetch(https://dog.ceo/api/breeds/image/random) if (!res.ok) { throw new Error(Response failed) } return { props: await res.json(), } } catch (error) { return { status: 500, headers: {}, props: {} } } }启动开发服务器并访问验证gatsby develop打开http://localhost:8000/ssr。每次刷新页面都会得到一张新的狗图——这正是每次请求都重新执行getServerData并重新渲染 HTML的直接体现。getServerData 返回值与 context 参数详解参考文档 server-side-rendering.md 给出了getServerData的完整签名。它返回的对象支持以下可选键status可选应返回给浏览器的 HTTP 状态码需为合法的 HTTP 状态码。上面的错误分支返回500即表示服务端内部错误。props可选传给页面serverDataprop 的数据对象必须是可序列化的即 JSON 兼容数据。headers可选随响应发送给浏览器以及缓存代理 / CDN 的 HTTP 响应头对象例如Cache-Control缓存头。这是 SSR 页面控制 CDN 缓存策略的关键手段。而getServerData(context)接收的context参数是一个包含以下键的对象键含义headers请求头request headersmethod请求方法如GETurl请求 URLquery表示查询字符串的对象params使用 File System Route API 时传入的 URL 路径参数。例如页面位于src/pages/{Product.name}.js则params形如{ name: value }pageContext页面的 context 对象这些参数在源码中有精确对应。在 get-server-data.ts 中Gatsby 使用match将实际请求路径与页面的matchPath/path做匹配来推导params并合并页面 context 中的__paramsFile System Route API 注入的路径参数headers被组装成一个Mapmethod默认回退为GET最终把组装好的参数对象原样传给用户定义的getServerData并返回其结果const getServerDataArg { headers: new Map(Object.entries(req?.headers ?? {})), method: req?.method ?? GET, url: req?.url ?? req most likely wasnt passed in, query: req?.query ?? {}, pageContext: page.context, params: { ...params, ...fsRouteParams, }, } return mod.getServerData(getServerDataArg)从源码结构看getServerData的返回值类型被定义为IServerDataheaders/props/status均为可选字段并且当模块未导出getServerData时该函数直接返回空对象——这也解释了为什么只有导出了该函数的页面才会走 SSR 路径。与构建期 GraphQL 查询的协同SSR 页面同样支持常规的 Gatsby GraphQL 页面查询。页面查询在构建期执行数据作为dataprop 在每次渲染时传给 React 组件与serverDataprop 并存。需要留意两者的时效差异data在每次渲染时都是相同的构建期快照而serverData会随getServerData的返回值每次变化。目前 Gatsby尚不支持运行时 GraphQL 查询。import * as React from react const Page ({ data, serverData }) { const { site } data const { dogImage } serverData // Use dogImage and site info in your page... } export const pageQuery graphql query PageData { site { siteMetadata { title } } } export async function getServerData() { const res await fetch(https://dog.ceo/api/breeds/image/random) const data await res.json() return { props: { dogImage: data, }, } } export default Page这种「构建期静态数据 请求期动态数据」的组合非常适合页面骨架标题、元信息等稳定、而主体内容高度动态的场景。本地开发与生产部署SSR 页面在gatsby develop和gatsby serve两种模式下均可工作页面会在每次请求时重新生成。需要特别强调的是SSR 依赖持续运行的 Node.js 服务器。生产环境需将运行gatsby serve的 Node 服务放在 CDN如 Fastly之后同时自行补齐监控、日志与崩溃恢复等基础设施。如果你的托管平台支持 Gatsby Functions / SSR例如 Gatsby Cloud可开箱即用地获得完整的自动伸缩部署。注意SSR 特性要求有运行的 NodeJS 服务器官方目前完整支持gatsby serve命令而纯静态托管如仅上传public目录的 CDN无法提供 SSR 能力。工作原理从请求到 HTML 的调用链从源码层面看SSR 的请求处理链清晰可循判断渲染模式Gatsby 通过getPageMode判断页面是否为 SSR即是否导出getServerData执行用户函数以gatsby serve为例在 start-server.ts 中服务器先通过renderer.getPageChunk(page)取到页面组件实例然后调用getServerData(req, page, potentialPagePath, componentInstance)获取服务端数据若返回对象带有headers则逐个通过res.setHeader写入响应头若带有status则覆盖默认的200状态码同时把result.props写入pageData.result.serverData供页面数据使用开发模式渲染在gatsby develop的 dev-ssr 路径render-dev-html.ts中同样先调用getServerData拿到serverData再把serverData.props作为渲染参数传给 HTML 渲染 worker最终把serverData与 HTML 一起返回。开发模式还支持?skip-ssr查询参数强制只渲染空壳页面以及渲染超时自动回退到客户端渲染的保护机制返回响应SSR 页面的 HTML 由服务端在请求期拼装完成start-server.tsserverData中的headers/status最终会应用到 HTTP 响应上。关于缓存参考文档明确说明SSR 模式下默认每次请求都是缓存未命中如需缓存必须自行设置自定义的 HTTPCache-Control响应头——这正是getServerData返回headers字段的核心价值所在。另外值得一提的是访问方式对返回内容的影响直接访问页面时你拿到的是服务端渲染好的 HTML而通过 Gatsby 的Link组件进行客户端导航时请求返回的是JSON由 Gatsby 的路由器在客户端据此渲染页面。这些行为全部自动完成你唯一需要做的就是在页面里定义一个getServerData函数。附加资源Server-Side Rendering API 参考指南Rendering Options 概念指南【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考