Next.js中服務器端渲染 (SSR) 詳解:動態內容與 SEO 的完美結合

Next.js中服務器端渲染 (SSR) 詳解:動態內容與 SEO 的完美結合

作者:碼力無邊


在上一篇文章中,我們深入探討了靜態站點生成 (SSG) 的強大之處,它通過在構建時預先生成頁面,為用戶提供了極致的訪問速度。但現實世界是動態多變的,并非所有頁面都能在構建時就確定其內容。

想象一下,一個用戶的個人儀表盤,其內容取決于當前登錄的是誰;或者一個電商網站的購物車頁面,其商品列表因人而異。對于這類高度動態化、個性化的內容,我們需要一種能夠在“最后一刻”——也就是在用戶請求到達時——才生成頁面的技術。這,就是服務器端渲染 (SSR) 的舞臺,而 getServerSideProps 則是它的核心執行者。

getServerSideProps:實時響應的“新聞記者”

讓我們再次回顧那個“新聞記者”的比喻。getServerSideProps 的工作模式就像一位時刻待命的記者:

  1. 用戶請求到達:瀏覽器向服務器發送一個特定頁面的請求,例如 /dashboard
  2. 服務器執行函數:Next.js 服務器接收到請求,立刻執行該頁面的 getServerSideProps 函數。這個函數可以訪問請求的詳細信息(如 cookies, headers)。
  3. 獲取實時數據:在函數內部,你可以連接數據庫、調用 API,獲取針對當前用戶或當前時間的最新數據。
  4. 實時渲染:Next.js 將獲取到的數據作為 props 注入頁面組件,并在服務器上實時渲染出完整的 HTML。
  5. 返回響應:服務器將這個新鮮出爐的 HTML 發送回瀏覽器。

這個過程確保了用戶看到的永遠是最新、最準確的內容。

何時應該選擇 SSR?

盡管我們強調“盡可能靜態化”,但 SSR 在以下場景中是不可或替代的:

  • 高度個性化的內容:頁面內容嚴重依賴于登錄用戶的信息。例如,用戶個人資料頁、訂單歷史、社交媒體的時間線。
  • 需要訪問請求對象 (Request Object):你需要根據請求的 headerscookies 或查詢參數來決定頁面內容。例如,根據用戶的 Accept-Language 頭來決定頁面的語言,或者通過 cookie 判斷用戶登錄狀態并決定是否重定向。
  • 數據頻繁且不可預測地變化:頁面的數據變化極快,無法通過 SSG 的定時再生(ISR)來有效更新。例如,股票交易應用的實時行情頁面。

一個常見的誤區:有人認為只要頁面有數據,就應該用 SSR。這是不對的。如果數據對于所有用戶都是一樣的(比如一篇博客),并且不需要每秒鐘都更新,那么 SSG 配合 ISR (后續會講) 是更好的選擇,因為它性能更高。只有當數據必須是“請求級”實時的時候,才需要 SSR。

getServerSideProps 實戰

讓我們構建一個簡單的場景:一個需要用戶登錄才能訪問的個人資料頁面。如果用戶未登錄,我們將他們重定向到登錄頁。

pages/profile.tsx

import type { GetServerSideProps, InferGetServerSidePropsType } from 'next';
import { parse } from 'cookie'; // 一個幫助解析 cookie 的庫type User = {id: string;name: string;email: string;
};// 模擬從數據庫根據用戶ID獲取用戶信息
const fetchUserById = async (userId: string): Promise<User | null> => {// 在真實應用中,這里會進行數據庫查詢if (userId === '123') {return { id: '123', name: '碼力無邊', email: 'user@example.com' };}return null;
};// 1. 定義 getServerSideProps,它接收一個 context 對象
export const getServerSideProps: GetServerSideProps<{ user: User }> = async (context) => {const { req, res } = context; // 從 context 中獲取 request 和 response 對象// 解析請求中的 cookieconst cookies = parse(req.headers.cookie || '');const userId = cookies.auth_token; // 假設我們的登錄 token 存在這里if (!userId) {// 如果沒有 token,說明用戶未登錄// 進行服務器端重定向return {redirect: {destination: '/login', // 重定向到登錄頁permanent: false, // false 表示這是一個臨時重定向},};}const user = await fetchUserById(userId);if (!user) {// 如果 token 無效或用戶不存在,也重定向到登錄頁return {redirect: {destination: '/login',permanent: false,},};}// 如果一切正常,將用戶信息作為 props 傳遞給頁面return {props: {user,},};
};// 2. 頁面組件接收 props
function ProfilePage({ user }: InferGetServerSidePropsType<typeof getServerSideProps>) {return (<div><h1>歡迎回來, {user.name}!</h1><p>您的郵箱是: {user.email}</p></div>);
}export default ProfilePage;

context 對象詳解

getServerSideProps 接收的 context 對象是一個寶庫,它包含了所有關于當前請求的信息:

  • req: Node.js 的 http.IncomingMessage 對象,包含了請求頭、cookies 等。
  • res: Node.js 的 http.ServerResponse 對象,可以用來設置響應頭。
  • params: 如果是動態路由,這里會包含路由參數(如 [id])。
  • query: URL 的查詢字符串部分,以對象形式表示。
  • resolvedUrl: 請求的完整 URL 路徑(不含域名)。
  • locale, locales: 與國際化 (i18n) 相關的信息。

SSR 的性能考量

SSR 雖然強大,但它是有成本的。每次請求都需要服務器進行計算,這被稱為 TTFB (Time to First Byte) 的開銷。如果你的 getServerSideProps 函數執行緩慢(例如,調用了一個很慢的 API),那么用戶將會看到一個更長的加載等待時間。

優化建議

  1. 確保數據源快速:你的數據庫查詢或 API 調用必須足夠快。
  2. 使用緩存:對于一些可以短時間緩存的數據,考慮在服務器端引入緩存層(如 Redis),避免每次都重復計算或請求。
  3. 謹慎使用:再次強調,不要濫用 SSR。問問自己:“這個頁面的數據真的需要在每次請求時都是最新的嗎?”如果答案是否定的,請考慮 SSG 或 ISR。

總結:SSG vs. SSR

我們現在已經深入了解了 Next.js 的兩種核心預渲染策略。讓我們用一張最終的對比圖來鞏固記憶:

對比維度getStaticProps (SSG)getServerSideProps (SSR)
核心理念構建時一次性生成每次請求實時生成
性能?? 極快 (CDN 邊緣分發)? 較快 (服務器實時計算)
適用場景博客、文檔、營銷頁 (內容對所有人一致)個人中心、購物車 (內容高度個性化、實時)
數據新鮮度構建時的快照絕對實時
SEO💯 完美💯 完美
開發中刷新數據只在構建時獲取每次刷新頁面都重新獲取數據

理解 SSG 和 SSR 的權衡是成為一名高效 Next.js 開發者的關鍵。它們不是競爭關系,而是互補的工具。一個復雜的應用通常會混合使用這兩種模式:用 SSG 構建大部分公開頁面以獲得最佳性能,用 SSR 來處理需要登錄和個性化的私有頁面。

我們的工具箱里現在有了兩個強大的工具。但如果我想要一個既有 SSG 的速度,又能像 SSR 一樣定期更新內容的“兩全其美”的方案呢?下一篇文章,我們將揭曉 Next.js 的又一個創新功能:增量靜態再生 (ISR),它將打破靜態與動態的界限。敬請期待!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/96362.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/96362.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/96362.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

c# winform 使用DevExpress制作表格

環境配置創建c# winform 新項目 test_devexpress添加引用把DevExpress.XtraGrid.v17.1.dll拖到工具箱在界面中&#xff0c;加入2個 GridControl設計器代碼&#xff1a;namespace test_devexpress {partial class Form1{/// <summary>/// 必需的設計器變量。/// </summ…

數據庫之間如何同步

數據庫之間如何同步&#xff1a;三種高效方法詳解 數據同步無小事&#xff0c;選對方法事半功倍 在現代數據驅動的環境中&#xff0c;??數據庫之間如何同步??是確保業務連續性和數據一致性的核心技術。本文將深入介紹三種主流的數據庫同步方法&#xff0c;幫助您根據實際需…

《我的世界》中實現強化學習(RL)算法

在《我的世界》中實現強化學習&#xff08;RL&#xff09;是一個巨大的挑戰&#xff0c;而獎勵函數&#xff08;Reward Function&#xff09;的設計是其中最核心、最困難的部分&#xff0c;直接決定了算法能否成功學習。 下面我將為你提供一個系統的設計框架、策略和注意事項。…

智能光場:深度學習重構計算光學成像新范式!

1.掌握深度學習算法的原理和應用&#xff0c;剖析計算成像主流研究范圍及關聯的統一計算范式&#xff0c;能夠運用深度學習技術對光學成像系統進行創新設計和優化。2.掌握利用深度學習從成像設備優化設計、典型計算成像任務以及后端的計算機視覺任務的認知框架&#xff0c;并掌…

深入理解 MyBatis-Plus 的 QueryWrapper:動態 SQL 構建的利器

關鍵詞&#xff1a;MyBatis-Plus、QueryWrapper、動態 SQL、Java、ORM 一、引言 在 Java 后端開發中&#xff0c;MyBatis-Plus&#xff08;簡稱 MP&#xff09;作為 MyBatis 的增強工具&#xff0c;極大地簡化了 CRUD 操作。而其中最核心的功能之一&#xff0c;就是動態 SQL 的…

WMIC用法

WMIC用法基本語法結構1. 全局開關&#xff08;可選&#xff0c;控制整體行為&#xff09;2. 別名&#xff08;Alias&#xff09;3. 動詞&#xff08;Verb&#xff09;4. 參數&#xff08;可選&#xff09;常用示例幫助命令WMIC&#xff08;Windows Management Instrumentation …

Spring Boot--yml配置信息書寫和獲取

案例&#xff1a;Spring Boot整合Mybatis步驟一&#xff1a;導入依賴步驟二&#xff1a;添加數據庫需要的數據源配置步驟三&#xff1a;編寫實體類步驟四&#xff1a;創建mapper類&#xff0c;操作數據庫步驟五&#xff1a;創建Service接口和接口實現類步驟六&#xff1a;創建C…

創作紀念日·512天

嘿嘿&#xff0c;不知不覺間&#xff0c;已經到了512天創作紀念日了。 回憶 遙想我在《我的創作紀念日》一篇中寫道&#xff0c;想要改名為 十二 &#xff0c;作為對過去生活的懷念&#xff0c;沒想到這個名字被搶了&#xff0c;好可惜。 想到25年4月13日寫紀念日博客時的自己…

在 Berachain 上,如何通過 BERA 實現一魚多吃?

Berachain 的 PoL&#xff08;Proof of Liquidity&#xff09;機制是其最具辨識度的創新之一。通過將 DeFi 的激勵邏輯深度嵌入共識層&#xff0c;不僅為底層網絡注入了充足的流動性&#xff0c;保障了安全性&#xff0c;同時也有效推動了生態應用的增長&#xff0c;更為用戶創…

LangGraph和aiagent

1. LangGraph&#xff1a;用圖思維重構Agent工作流LangGraph是LangChain團隊開源的圖式Agent編排框架&#xff0c;它基于"有向圖"模型&#xff0c;將Agent的運行流程抽象為"節點 狀態流轉"。其核心設計理念是用有向狀態圖&#xff08;Directed State Grap…

《從iptables到ipvs:云原生網絡轉發的性能拐點突破》

這套基于Spring Cloud Alibaba搭建的架構,部署于阿里云ACK集群的10個4核8G節點上,默認配置6個Pod副本,搭配HPA彈性擴縮容機制與Ingress網關流量分發,理論上具備應對3倍日常流量的承載能力。然而實際運行中,每日早9點、午2點、晚8點三次流量峰值來臨時,訂單服務會在120秒內…

大數據存儲域——Kafka設計原理

摘要本文主要介紹了Kafka的架構原理、消息訂閱模式以及在金融風控等領域的應用。Kafka作為數據中轉站&#xff0c;可同步不同系統數據&#xff0c;支持事件驅動架構&#xff0c;廣泛應用于金融支付與風控場景。其架構包括Producer、Broker、Topic、Partition、Replication、Mes…

[特殊字符] GitHub 熱門開源項目速覽(2025/09/09)

今天為大家整理了近期 GitHub 上熱度較高的開源項目&#xff0c;涵蓋 AI Agent、加密計算、操作系統、機器人、PDF 工具 等多個方向。讓我們一起看看都有哪些值得關注的項目吧&#xff01; &#x1f539; AI Agents & 開發者工具 parlant &#xff08;? 10.9k | ?? 117…

OpenHarmony之USB Manager 架構深度解析

1. 整體架構 OpenHarmony USB管理器采用三層架構設計: USB API:提供USB的基礎API,主要包含查詢USB設備的列表、設備插拔通知、USB HOST/DEVICE 功能切換、批量數據傳輸、控制命令傳輸、USB設備打開的權限控制及USB device模式下的function功能切換等。 USB Service:主要實…

java面試中經常會問到的mysql問題有哪些(基礎版)

文章目錄一、基礎概念與存儲引擎二、索引設計與優化&#xff08;高頻重點&#xff09;三、事務與鎖&#xff08;核心原理&#xff09;四、SQL性能優化與問題排查五、高可用與數據安全六、其他高頻細節問題在Java面試中&#xff0c;MySQL作為最常用的關系型數據庫&#xff0c;是…

Tess-two - Tess-two 文字識別(Tess-two 概述、Tess-two 文字識別、補充情況)

一、Tess-two 概述Tess-two 是 Tesseract OCR 引擎在 Android 平臺上的一個封裝庫&#xff0c;用于實現離線文字識別Tess-two 的 GitHub 官網&#xff1a;https://github.com/rmtheis/tess-two二、Tess-two 文字識別 1、演示 &#xff08;1&#xff09;Dependencies 模塊級 bui…

八、Win/Linux/macOS全平臺徹底卸載Docker的操作指南

八、Win/Linux/macOS全平臺徹底卸載Docker的操作指南 系列文章目錄 1. 卸載前準備工作(可忽略) 1.1 數據備份 1.2 停止Docker服務 2. 不同操作系統卸載步驟 2.1 Linux系統 2.2 macOS系統 2.3 Windows系統 3. 殘留文件深度清理 3.1 Linux系統 3.2 macOS系統 3.3 Windows系統 4…

強化學習-CH9 策略梯度方法

強化學習-CH9 策略梯度方法 當策略被表示為函數時&#xff0c;通過優化目標函數可以得到最優策略。 這種方法稱為策略梯度。策略梯度方法是基于策略的&#xff0c;而之前介紹的方法都是基于值的。其本質區別在于基于策略的方法是直接優化關于策略參數的目標函數。 9.1 策略表示…

[玩轉GoLang] 5分鐘整合Gin / Gorm框架入門

方法 / 步驟 一: Gin框架 1.1 : 環境 & 項目配置 1, GoLand創建項目 創建main.go package mainimport ("github.com/gin-gonic/gin" )func main() {r : gin.Default()r.GET("/", func(c *gin.Context) {c.JSON(200, gin.H{"message": "…

【項目復現】MOOSE-Chem 用于重新發現未見化學科學假說的大型語言模型

項目地址 ZonglinY/MOOSE-Chem: [ICLR 2025] --- ZonglinY/MOOSE-Chem: [ICLR 2025] https://github.com/ZonglinY/MOOSE-Chem git代碼同步&#xff1a; 同步地址如下&#xff1a;QianPengfei1/MOOSE-Chem: [ICLR 2025] <MOOSE-Chem: Large Language Models for Rediscove…