端渲染(SSR)完全指南:使用 getServerData 按請(qǐng)求動(dòng)態(tài)渲染頁(yè)面)
Gatsby 服務(wù)端渲染SSR完全指南使用 getServerData 按請(qǐng)求動(dòng)態(tài)渲染頁(yè)面【免費(fèi)下載鏈接】gatsbyReact-based framework with performance, scalability, and security built in.項(xiàng)目地址: https://gitcode.com/gh_mirrors/ga/gatsby本文是圍繞 Gatsby 服務(wù)端渲染Server-Side RenderingSSR的實(shí)戰(zhàn)指南講解如何通過(guò)頁(yè)面組件導(dǎo)出的getServerData函數(shù)讓 Gatsby 在用戶(hù)每次訪(fǎng)問(wèn)頁(yè)面時(shí)動(dòng)態(tài)拉取數(shù)據(jù)并預(yù)渲染 HTML。讀完本文你將掌握 SSR 頁(yè)面的創(chuàng)建方法、getServerData的返回值與context參數(shù)語(yǔ)義、它與構(gòu)建期 GraphQL 查詢(xún)的協(xié)作方式以及 SSR 在gatsby develop/gatsby serve下的底層工作機(jī)理能夠針對(duì)動(dòng)態(tài)個(gè)性化、鑒權(quán)數(shù)據(jù)、A/B 測(cè)試等場(chǎng)景做出正確的渲染方案選型。SSR 在 Gatsby 渲染選項(xiàng)中的定位Gatsby 自 4.0 起在默認(rèn)的靜態(tài)站點(diǎn)生成SSG基礎(chǔ)上引入了按頁(yè)可選的渲染模式Deferred Static GenerationDSG與 Server-Side RenderingSSR。SSR 允許你在用戶(hù)訪(fǎng)問(wèn)頁(yè)面的那一刻拉取數(shù)據(jù)并預(yù)渲染頁(yè)面——服務(wù)器在收到 HTTP 請(qǐng)求期間生成完整 HTML 并返回給用戶(hù)數(shù)據(jù)獲取發(fā)生在 Gatsby 數(shù)據(jù)層之外。概念文檔 rendering-options.md 明確指出渲染選項(xiàng)定義的是頁(yè)面面向用戶(hù)的 HTML 在哪個(gè)階段生成——構(gòu)建期SSG / 預(yù)渲染、HTTP 請(qǐng)求期間SSR或由瀏覽器端 JavaScript 完成CSR。SSG 是 Gatsby 的默認(rèn)模式全部 HTML/CSS/JS 在構(gòu)建期生成并作為靜態(tài)資源發(fā)布因此訪(fǎng)問(wèn)速度最快DSG 則允許開(kāi)發(fā)者把低流量頁(yè)面推遲到首次請(qǐng)求時(shí)再生成以換取更短的構(gòu)建時(shí)間。雖然官方推薦優(yōu)先使用 SSG 或 DSG但 SSR 在一些特定場(chǎng)景下不可替代動(dòng)態(tài)個(gè)性化根據(jù)用戶(hù)身份、地理位置渲染不同內(nèi)容鑒權(quán)數(shù)據(jù)需要登錄態(tài)的私有數(shù)據(jù)且希望搜索引擎能索引A/B 測(cè)試按用戶(hù)分組動(dòng)態(tài)分配實(shí)驗(yàn)版本時(shí)效性要求高的內(nèi)容如用戶(hù)評(píng)論需要發(fā)布后立即被搜索引擎收錄客戶(hù)端渲染無(wú)法滿(mǎn)足。如果你不需要預(yù)渲染頁(yè)面僅在瀏覽器端拉數(shù)據(jù)即可則可退而使用 client-only routes客戶(hù)端專(zhuān)屬路由無(wú)需引入 SSR 的服務(wù)器成本。SSR 的完整 API 細(xì)節(jié)可參考 Server-Side Rendering API 參考文檔。如上圖所示SSR 模式下每一次請(qǐng)求都會(huì)經(jīng)過(guò)服務(wù)器執(zhí)行渲染邏輯dashboard.js等頁(yè)面腳本并可能調(diào)用第三方 API之后再返回響應(yīng)——這與 SSG 命中的 CDN 緩存流程有本質(zhì)區(qū)別。前置條件開(kāi)始之前你需要有一個(gè)可運(yùn)行的 Gatsby 站點(diǎn)。如果還沒(méi)有可以參照 Quick Start 快速創(chuàng)建一個(gè)。實(shí)現(xiàn)步驟概覽SSR 的使用流程非常精簡(jiǎn)只有兩步在頁(yè)面組件中添加getServerData函數(shù)在getServerData內(nèi)部請(qǐng)求數(shù)據(jù)并把結(jié)果渲染到頁(yè)面上。下文以「隨機(jī)狗圖」頁(yè)面為例數(shù)據(jù)源為 dog.ceo 公共 API逐步演示。請(qǐng)新建頁(yè)面文件src/pages/ssr.js。Step 1添加getServerData函數(shù)只要在頁(yè)面組件中導(dǎo)出一個(gè)名為getServerData的 async 函數(shù)Gatsby 就會(huì)自動(dòng)為該頁(yè)面選擇 SSR 渲染模式。先寫(xiě)一個(gè)只含標(biāo)題的空頁(yè)面import * as React from react const SSRPage () ( main h1SSR Page with Dogs/h1 /main ) export default SSRPage export async function getServerData() {} // highlight-line僅憑這一行空函數(shù)頁(yè)面就完成了從 SSG 到 SSR 的切換。參考文檔強(qiáng)調(diào)你只能在頁(yè)面文件中導(dǎo)出getServerData不能從非頁(yè)面文件導(dǎo)出它——Gatsby 會(huì)掃描頁(yè)面組件并據(jù)此決定渲染模式。Step 2在getServerData中請(qǐng)求數(shù)據(jù)并展示getServerData內(nèi)可以執(zhí)行任意邏輯但必須返回一個(gè)包含props的對(duì)象。返回的props會(huì)被 Gatsby 注入到頁(yè)面組件上成為名為serverData的 prop——這與頁(yè)面查詢(xún)page query自動(dòng)把結(jié)果作為dataprop 傳入的機(jī)制類(lèi)似。使用原生fetch從 dog.ceo API 拉取隨機(jī)狗圖// 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: {} } } }此后用戶(hù)每次訪(fǎng)問(wèn)該頁(yè)面服務(wù)器都會(huì)請(qǐng)求https://dog.ceo/api/breeds/image/random并把響應(yīng)作為serverData提供給頁(yè)面組件。該 API 的響應(yīng)結(jié)構(gòu)為{ message: img-url, status: }?,F(xiàn)在把圖片渲染出來(lái)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: {} } } }啟動(dòng)開(kāi)發(fā)服務(wù)器并訪(fǎng)問(wèn)驗(yàn)證gatsby develop打開(kāi)http://localhost:8000/ssr。每次刷新頁(yè)面都會(huì)得到一張新的狗圖——這正是每次請(qǐng)求都重新執(zhí)行g(shù)etServerData并重新渲染 HTML的直接體現(xiàn)。getServerData 返回值與 context 參數(shù)詳解參考文檔 server-side-rendering.md 給出了getServerData的完整簽名。它返回的對(duì)象支持以下可選鍵status可選應(yīng)返回給瀏覽器的 HTTP 狀態(tài)碼需為合法的 HTTP 狀態(tài)碼。上面的錯(cuò)誤分支返回500即表示服務(wù)端內(nèi)部錯(cuò)誤。props可選傳給頁(yè)面serverDataprop 的數(shù)據(jù)對(duì)象必須是可序列化的即 JSON 兼容數(shù)據(jù)。headers可選隨響應(yīng)發(fā)送給瀏覽器以及緩存代理 / CDN 的 HTTP 響應(yīng)頭對(duì)象例如Cache-Control緩存頭。這是 SSR 頁(yè)面控制 CDN 緩存策略的關(guān)鍵手段。而getServerData(context)接收的context參數(shù)是一個(gè)包含以下鍵的對(duì)象鍵含義headers請(qǐng)求頭request headersmethod請(qǐng)求方法如GETurl請(qǐng)求 URLquery表示查詢(xún)字符串的對(duì)象params使用 File System Route API 時(shí)傳入的 URL 路徑參數(shù)。例如頁(yè)面位于src/pages/{Product.name}.js則params形如{ name: value }pageContext頁(yè)面的 context 對(duì)象這些參數(shù)在源碼中有精確對(duì)應(yīng)。在 get-server-data.ts 中Gatsby 使用match將實(shí)際請(qǐng)求路徑與頁(yè)面的matchPath/path做匹配來(lái)推導(dǎo)params并合并頁(yè)面 context 中的__paramsFile System Route API 注入的路徑參數(shù)headers被組裝成一個(gè)Mapmethod默認(rèn)回退為GET最終把組裝好的參數(shù)對(duì)象原樣傳給用戶(hù)定義的getServerData并返回其結(jié)果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)從源碼結(jié)構(gòu)看getServerData的返回值類(lèi)型被定義為IServerDataheaders/props/status均為可選字段并且當(dāng)模塊未導(dǎo)出getServerData時(shí)該函數(shù)直接返回空對(duì)象——這也解釋了為什么只有導(dǎo)出了該函數(shù)的頁(yè)面才會(huì)走 SSR 路徑。與構(gòu)建期 GraphQL 查詢(xún)的協(xié)同SSR 頁(yè)面同樣支持常規(guī)的 Gatsby GraphQL 頁(yè)面查詢(xún)。頁(yè)面查詢(xún)?cè)跇?gòu)建期執(zhí)行數(shù)據(jù)作為dataprop 在每次渲染時(shí)傳給 React 組件與serverDataprop 并存。需要留意兩者的時(shí)效差異data在每次渲染時(shí)都是相同的構(gòu)建期快照而serverData會(huì)隨getServerData的返回值每次變化。目前 Gatsby尚不支持運(yùn)行時(shí) GraphQL 查詢(xún)。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這種「構(gòu)建期靜態(tài)數(shù)據(jù) 請(qǐng)求期動(dòng)態(tài)數(shù)據(jù)」的組合非常適合頁(yè)面骨架標(biāo)題、元信息等穩(wěn)定、而主體內(nèi)容高度動(dòng)態(tài)的場(chǎng)景。本地開(kāi)發(fā)與生產(chǎn)部署SSR 頁(yè)面在gatsby develop和gatsby serve兩種模式下均可工作頁(yè)面會(huì)在每次請(qǐng)求時(shí)重新生成。需要特別強(qiáng)調(diào)的是SSR 依賴(lài)持續(xù)運(yùn)行的 Node.js 服務(wù)器。生產(chǎn)環(huán)境需將運(yùn)行g(shù)atsby serve的 Node 服務(wù)放在 CDN如 Fastly之后同時(shí)自行補(bǔ)齊監(jiān)控、日志與崩潰恢復(fù)等基礎(chǔ)設(shè)施。如果你的托管平臺(tái)支持 Gatsby Functions / SSR例如 Gatsby Cloud可開(kāi)箱即用地獲得完整的自動(dòng)伸縮部署。注意SSR 特性要求有運(yùn)行的 NodeJS 服務(wù)器官方目前完整支持gatsby serve命令而純靜態(tài)托管如僅上傳public目錄的 CDN無(wú)法提供 SSR 能力。工作原理從請(qǐng)求到 HTML 的調(diào)用鏈從源碼層面看SSR 的請(qǐng)求處理鏈清晰可循判斷渲染模式Gatsby 通過(guò)getPageMode判斷頁(yè)面是否為 SSR即是否導(dǎo)出getServerData執(zhí)行用戶(hù)函數(shù)以gatsby serve為例在 start-server.ts 中服務(wù)器先通過(guò)renderer.getPageChunk(page)取到頁(yè)面組件實(shí)例然后調(diào)用getServerData(req, page, potentialPagePath, componentInstance)獲取服務(wù)端數(shù)據(jù)若返回對(duì)象帶有headers則逐個(gè)通過(guò)res.setHeader寫(xiě)入響應(yīng)頭若帶有status則覆蓋默認(rèn)的200狀態(tài)碼同時(shí)把result.props寫(xiě)入pageData.result.serverData供頁(yè)面數(shù)據(jù)使用開(kāi)發(fā)模式渲染在gatsby develop的 dev-ssr 路徑render-dev-html.ts中同樣先調(diào)用getServerData拿到serverData再把serverData.props作為渲染參數(shù)傳給 HTML 渲染 worker最終把serverData與 HTML 一起返回。開(kāi)發(fā)模式還支持?skip-ssr查詢(xún)參數(shù)強(qiáng)制只渲染空殼頁(yè)面以及渲染超時(shí)自動(dòng)回退到客戶(hù)端渲染的保護(hù)機(jī)制返回響應(yīng)SSR 頁(yè)面的 HTML 由服務(wù)端在請(qǐng)求期拼裝完成start-server.tsserverData中的headers/status最終會(huì)應(yīng)用到 HTTP 響應(yīng)上。關(guān)于緩存參考文檔明確說(shuō)明SSR 模式下默認(rèn)每次請(qǐng)求都是緩存未命中如需緩存必須自行設(shè)置自定義的 HTTPCache-Control響應(yīng)頭——這正是getServerData返回headers字段的核心價(jià)值所在。另外值得一提的是訪(fǎng)問(wèn)方式對(duì)返回內(nèi)容的影響直接訪(fǎng)問(wèn)頁(yè)面時(shí)你拿到的是服務(wù)端渲染好的 HTML而通過(guò) Gatsby 的Link組件進(jìn)行客戶(hù)端導(dǎo)航時(shí)請(qǐng)求返回的是JSON由 Gatsby 的路由器在客戶(hù)端據(jù)此渲染頁(yè)面。這些行為全部自動(dòng)完成你唯一需要做的就是在頁(yè)面里定義一個(gè)getServerData函數(shù)。附加資源Server-Side Rendering API 參考指南Rendering Options 概念指南【免費(fèi)下載鏈接】gatsbyReact-based framework with performance, scalability, and security built in.項(xiàng)目地址: https://gitcode.com/gh_mirrors/ga/gatsby創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考