Next.js 中的靜態與動態——終于搞懂了
很多前端同學寫 Next.js,概念都懂,文檔也看,真正開寫的時候卻總在糾結:
這一頁到底該靜態?還是動態? 用 SSG?SSR?還是干脆全放到客戶端拉?
到最后,腦子里只有一句保命咒: ——“算了,全用 getServerSideProps,最穩?!?/span>
結果是: 項目能跑,但不快、不省錢、不好維護。
直到有一天,有人把這件事想明白成一句超級簡單的話 ??
那個終于想明白的心智模型:只問一句話
每一個頁面、每一個組件,其實都在回答同一個問題:
“這塊內容,在 構建時 能不能確定?”
- 能 —— 就靜態。
- 不能 —— 就動態。
就這么簡單。 所有文檔、名詞、模式,歸根結底都繞不出這句話。
但真正落到實戰,還需要一些具體場景來扎心。
靜態頁面:那些“不怎么變”的內容
Next.js 里的 靜態生成(Static Generation)(比如 getStaticProps),真正厲害的地方在于:
- 性能更猛:HTML 預渲染好,響應極快
- SEO 更香:首屏就有完整 HTML
- 服務器更省錢:請求來了幾乎不需要算力
適用場景非常清晰:
- 博客詳情頁
- 營銷 / 官網頁
- 很少變動的產品詳情
- 不做個性化的首頁
一句話:
“絕大多數用戶看到的是同一份內容,而且不怎么變” — 就讓它靜態。
如果又想靜態、又怕太“陳舊”,
這時候就輪到 ISR(增量靜態再生)上場了:
export async function getStaticProps() {
const data = await fetchPosts();
return {
props: { data },
revalidate: 60, // 每 60 秒后臺重建一次頁面
};
}用 revalidate 做一個折中:
- 平時用戶訪問的是緩存好的靜態頁
- 到了重建時間,后臺悄悄刷新一版新的
- 整體體驗:既快,又不會舊到離譜
動態頁面:要么老在變,要么因人而異
動態渲染(Dynamic Rendering),不管是 getServerSideProps 還是純客戶端請求, 適合的就是這一類:
- 和用戶強相關(登錄信息、權限、私人數據)
- 強依賴實時變化(庫存、價格、交易狀態)
- 每次請求都很可能不一樣(搜索、篩選、排序)
典型姿勢是用 getServerSideProps:
export async function getServerSideProps(context) {
const session = await getSession(context);
const userData = await getUserData(session.user.id);
return { props: { userData } };
}適合用在:
- 登錄后的儀表盤 / 控制臺
- 嚴格權限控制的內容
- 每次刷新都必須最新的數據
如果頁面本身很互動、狀態很多, 也可以干脆把數據請求丟給客戶端去做:
- SWR
- React Query
- 自己封裝的 fetch Hook
讓頁面先有一個殼,數據再源源不斷填進去。
一張小表,直接對號入座
場景 | 靜態 Static | 動態 Dynamic |
博客文章詳情 | ? | |
登錄后的個人儀表盤 / 控制臺 | ? | |
首頁 + 偶爾更新的用戶評價 | ? + ISR | |
搜索結果頁面 | ? | |
經常變化的產品價格 | ? 或 ? + ISR | |
營銷落地頁 / 產品介紹頁 | ? |
如果還猶豫,就把這三個問題在心里過一遍:
- 這塊內容,對所有用戶是不是一樣?
- 它變化的頻率高不高?
- 是不是每一次請求,都必須拿到“最新的那一份”?
答案越偏向“穩定、通用、不那么頻繁變化”,就越適合靜態。 反之,就越適合動態。
想清楚之后,優先級就變了
很多人剛上手 Next.js 時,都習慣性地用 getServerSideProps:
“反正 SSR 什么都能做,多一層保險。”
結果是:
- 每個請求都要打服務器
- 頁面響應不算慢,但也肯定不快
- 服務器賬單和復雜度都往上堆
換一個視角之后,新的優先級變成:
- 速度優先 ? — 能靜態就靜態
- 成本可控 ?? — 能不算就不算
- 體驗舒服 ?? — 只在必要時才上動態
盡量讓 Next.js 幫忙“預算好一切能預算的東西”, 服務器的算力留給真正“必須每次實時計算”的部分。
Bonus:頁面可以“外冷內熱”混搭
很多人潛意識里會以為:
“要么整站靜態,要么整站動態?!?/span>
實際上,Next.js 完全支持混搭模式:
- 頁面骨架用靜態生成
- 局部數據用客戶端動態拉取
比如:
// 外層是靜態頁面
export default function Page({ staticData }) {
const { data: liveData } = useSWR('/api/live');
return (
<div>
<Hero data={staticData} />
<LiveStats data={liveData} />
</div>
);
}這樣一來:
- Hero 區域永遠能“秒開”
- LiveStats 用 SWR 慢慢拉最新數據
- 用戶既感覺頁面“開得快”,又享受“數據是活的”
這種“靜態殼 + 動態數據”的模式, 對于首頁、詳情頁、儀表盤,都非常好用。
總結:一句話就夠了
真正的心智突圍點,其實就一句話:
“只要能在構建時生成,就先靜態; 只有實在做不到,才上動態。”
Next.js 已經把工具全部擺在桌面上:
getStaticProps/getStaticPaths- ISR 的
revalidate getServerSideProps- SWR / React Query
真正拉開差距的,是:
- 誰能分清楚哪一塊內容該用什么方式渲染
- 誰能在“方便”和“成本”、“體驗”和“結構”之間,做出更聰明的取舍
項目的靜態 vs 動態, 其實就是開發者對“數據本質”的一次次判斷題。 答對次數越多,Next.js 項目的表現,就會越像一臺真正為用戶服務的機器,而不只是“能跑起來的框架示例”。




































