Next.js 的 server 邊界:哪些留在框架,哪些丟出去

Next.js 把「server 能做的事」鋪得很滿,滿到很多人沒先想清楚就把東西全往裡塞。15 版(2024 年 10 月發布)之後 App Router、RSC 算是站穩了,工具夠成熟,反而更該回頭問一句:這四個縮寫,到底各自在解什麼問題,哪些東西適合留在框架的 server,哪些該丟出去。

先把四個縮寫分清楚

SSR 是每次請求都在 server 把頁面生出來,適合內容會隨人、隨時間變的頁面。SSG 是 build 的時候一次生好,之後就是靜態檔,適合那種「全世界看到的都一樣、改動不頻繁」的頁,行銷頁、文件站。ISR 卡在中間:先用快取的版本回,背景按需重生,讓你不必為了一點新鮮度就把整站打回 SSR,也不必每次內容微調就 rebuild 全站。這三個講的是同一件事的不同時間點,HTML 在「什麼時候、生幾次」。

RSC 是另一個維度。它不是在問 HTML 何時生,而是在問「這段元件的 JS 要不要送到瀏覽器」。server component 在 server 跑完,把結果序列化送過去,那段邏輯與它拉進來的相依套件就不進 client bundle。這對 bundle size 是實打實的好處,資料抓取也可以更靠近 server。但它跟 SSR 不是同義詞,混在一起談就會開始講不清楚自己到底想要哪一段。

我看人踩坑,幾乎都是把「何時生 HTML」和「JS 送不送 client」這兩件事攪在一起。先在腦子裡把它們分成兩個獨立的軸,後面的決定才會清楚。

給瀏覽器的聚合,跟面向後端的風險邏輯

真正要劃的線不在這四個縮寫之間,在另一處:你寫在 server 上的這段碼,是「替瀏覽器把畫面要的資料聚合好」,還是「面向後端、跨服務、帶風險的邏輯」。

API routes、server actions、server components 都跑在 server,但責任不該混。前者是聚合:這個頁面要顯示的東西散在三五個下游,你在 Next 的 server 段把它們抓回來、拼成畫面需要的結構、順手裁掉用不到的欄位。這種「為這個畫面服務」的聚合,留在 Next server 很合理,它本來就最懂自己的頁面要什麼。

後者不一樣。跨多個服務的交易、寫入核心資料、帶著下游位址與內部認證的呼叫、第三方的 API key,這類東西我傾向丟出去,放獨立的 BFF 或後端服務,別塞進 framework server。理由跟我一貫的立場一致:邊界要靠結構扛住,不是靠自律。一段 server action 看起來人畜無害,但它能直接 import 到你的資料層、能讀到 env 裡的 key,你就是在賭哪段碼會不會不小心被牽進 client,賭 build 工具有沒有幫你切俐落。把帶風險的邏輯關在一個獨立、邊界清楚的服務裡,Next 這端連那些端點存在都不需要知道,這才是結構上的安全。

還有 lock-in。聚合邏輯綁在 Next 的 server runtime 上,問題不大,那本來就是展示層的一部分。但你把跨服務的核心邏輯、認證、對外整合全長在 server action 與 route handler 裡,哪天想換框架、想把這套搬到別的 runtime,會發現業務邏輯跟 Next 的執行模型纏死了。把這層抽到框架外,Next 對它來說只是其中一個 caller,換不換框架都不動它。

用之前,先承認它的成本

我不是在唱衰 RSC。它把該留 server 的東西留在 server,這個方向我認同。但說實話:複雜度與成本是真的。RSC 與 client component 的邊界、"use client" 該畫在哪、哪些 props 能跨那條線序列化,這些都是新的學習成本。hydration 也不是沒有代價,server 送來的標記要在 client 接手,這層 overhead 在互動密集的頁面會反咬你。

Next 生態的 lock-in 確實存在。App Router 的 caching 行為、RSC 的邊界規則,都帶著相當的 framework 特定知識,學的是「Next 怎麼想」,不完全是「web 怎麼運作」。這跟我長期的不安一致:框架抽象太深,人會慢慢失去對 HTTP、對瀏覽器在做什麼的直覺。所以用之前先想清楚你要的是哪一段:要的是 SSG 的靜態與快,還是 ISR 的按需新鮮,還是 RSC 的 bundle 瘦身。把要的那段拿走,其餘別因為「框架支援」就全開。能 build 不等於設計合理。

重點整理

  • SSR / SSG / ISR 講的是 HTML 何時生、生幾次,RSC 講的是 JS 送不送 client,先當成兩條獨立的軸。
  • 給瀏覽器的畫面聚合留在 Next server 合理,它最懂自己頁面要什麼。
  • 跨服務、寫核心資料、帶下游認證與 key 的風險邏輯丟獨立 BFF,別塞進 framework server。
  • 安全靠結構不靠自律:把端點關在框架外,client 連它存在都不知道。
  • RSC 與 hydration 有真實成本與 lock-in,用之前先確定你要的是哪一段,別因為框架支援就全開。

觀點 Sheng,內文 Claude 協助 · 列入 20260613 blog 翻新計劃,新漆未乾。