3.1 Jamstack 與靜態優先架構:為什麼快取是最好的後端#
本節目標#
在動手架站之前,先回答一個根本問題:現代網站為什麼要「靜態優先」? 本節回顧從 CGI 到動態頁的歷史、Jamstack 的誕生脈絡,說明「預先建置 + 邊緣快取」為何在延遲、成本與安全性上都勝過每次請求都現做的傳統架構,最後以對照表釐清靜態生成(SSG)與伺服器端渲染(SSR)的差異,為第 3.2、3.3 節的實作鋪路。
歷史:從 CGI 到動態頁的代價#
Web 最初的形態極其簡單:伺服器上放一堆 .html 檔,請求來了就原樣回傳。1993 年 CGI(Common Gateway Interface)問世,讓網頁能「現場產生」——每個請求 spawn 一個處理程序跑 Perl 腳本、查資料庫、拼出 HTML。
CGI 時代(1993-):
瀏覽器 → Apache → fork() 處理程序 → 執行 Perl/PHP → 查 DB → 拼 HTML → 回傳
這開啟了動態 Web(留言板、購物車),但也埋下三個代價:
- 延遲:每次請求都要現場運算,使用者等的是「伺服器的翻譯時間」。
- 成本:伺服器必須常駐、隨流量擴容;沒人看時資源照樣燒錢。
- 攻擊面:動態程式碼直接暴露在公網,SQL Injection、RCE 都發生在這一層。
此後三十年,架構史可粗略濃縮為一句話:把「現做」推回「先做好」,把運算從中心推到邊緣。
| 年代 | 形態 | 關鍵字 |
|---|---|---|
| 1993 | CGI / 動態頁 | 每請求現做 |
| 2005 | 快取層(Squid、Varnish、Memcached) | 把熱門頁「記住」 |
| 2010s | CDN 普及 | 快取推到全球邊緣 |
| 2016 | Jamstack | 連建置都提前完成:部署即靜態 |
Jamstack 詞源:JavaScript、APIs、Markup#
2016 年,Netlify 執行長 Mathias Biillmann 與創辦人系統性地命名了這股潮流——Jamstack:
JavaScript + APIs + prebuilt Markup,無需自管 Web 伺服器。
核心主張只有一條公式:
注意 stack 不是技術棧,而是「分層拆開」的意思:Markup(視圖)、JS(互動)、APIs(資料)三層各自獨立演化、各自快取。動態的部分不是不存在,而是被推到兩端——前端交給瀏覽器執行,資料交給 API(在我們的書中,就是稍後的 Pages Functions 與 Workers)。
為何快取優先:三條數學上的勝利#
延遲:CDN 邊緣節點離使用者往往 <50ms,而回源到中央伺服器再運算常 >300ms。快取命中時:
成本:靜態檔案由邊緣以近乎零邊際成本服務,不需要為「深夜的十個訪客」養一台 24 小時伺服器。
安全:公網上沒有可執行的伺服器程式碼,就沒有可攻擊的伺服器程式碼——攻擊面只剩靜態檔案與你「主動提供」的 API 端點。
不可變部署:快取能大膽的前提#
Jamstack 能放心「永久快取」,靠的是內容定址(content-addressable)的檔名:
/assets/index.a8f3c1.js ← 檔名含內容雜湊,內容一變檔名就變
於是「更新網站」從「修改伺服器上的檔案(快取全部作廢)」變成「部署一批全新檔名的新檔案(舊快取永遠有效)」。Cloudflare Pages 在 3.4 節會看到,它把每個部署整個凍結成不可變的版本目錄,正是這個理念的產品化。
靜態優先與 Islands Architecture#
「靜態優先」不是「全部靜態」,而是預設靜態、按需注水:
┌──────────────────────────────┐
│ 99% 是純 HTML/CSS(島的海洋) │
│ ┌────┐ ┌────┐ │
│ │島1 │ 靜態海 │島2 │ │
│ │搜尋│ │留言│ │
│ └────┘ └────┘ │
└──────────────────────────────┘
Islands Architecture(群島架構):整頁是伺服器預先渲染好的靜態 HTML;只有少數需要互動的元件(島)單獨載入 JS 並「注水(hydrate)」。頁面上沒有互動的部分零 JS、零水合成本 —— 這是 Astro 的核心設計(3.2 節將實際使用)。
靜態生成 vs 伺服器端渲染#
| 面向 | SSG(Static Site Generation) | SSR(Server-Side Rendering) |
|---|---|---|
| 何時產生 HTML | 部署/建置時,一次性 | 每個請求,現場運算 |
| 執行位置 | CI 機器(建一次) | 每台伺服器/邊緣運算 |
| 邊緣快取 | 天然可快取、永久有效 | 需 TTL 與失效策略 |
| 資料新鮮度 | 建置那一刻的快照 | 永遠最新 |
| 延遲 | 最低(純 CDN 命中) | 較高(運算 + 可能查 DB) |
| 成本 | 幾乎為零 | 隨流量線性成長 |
| 適合 | 文件、部落格、行銷頁、作品集 | 搜尋、個人化 Feed、結帳頁 |
本書的取捨原則:能靜態就靜態,動態資料用 API 補。部落格文章是建置時從 Git/Markdown 生成的靜態頁(SSG);留言、點讚這類即時資料,由瀏覽器呼叫邊緣 API取得——兩全其美,且完全跑在 Cloudflare 免費方案內。
小結與練習#
本節確認了靜態優先的理論根基:CGI 以來的動態代價(延遲、成本、攻擊面)催生了 Jamstack——把 Markup 提前建置、把互動留在瀏覽器、把資料推給 API,讓全球邊緣快取成為最好的「後端」。
練習
- 打開任一你常逛的大型網站,用開發者工具 Network 面板觀察:HTML 是 server-rendered 還是 CDN 快取的靜態檔?哪些資源是請求後才由 JS 載入的「島」?
- 把「留言板」用本節的公式拆解:哪些屬於 prebuilt Markup?哪些屬於瀏覽器 JS?哪些屬於 API?
- 思考題:若一個頁面每分鐘資料都在變(股價頁),Jamstack 還適用嗎?提示:增量靜態再生成(ISR)、短 TTL 快取與純 SSR 各有何取捨?
下一節動手建立前端專案。