[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fH8FpXHoAOSrDfcDGJM8aSSCg9NPxo2fDLcqkRxUeyK0":3},{"slug":4,"title":5,"body":6,"excerpt":7,"tags":8,"maturity":12,"meta":13,"plantedAt":14,"tendedAt":15,"shouldIndex":16,"resolvedLinks":17,"backlinks":19,"authorName":29},"ssr-rendering-modes","SSG、ISR、SSR：一個站三種渲染，逐路由挑","「SSR 還是 SSG？」是個假問題——正確的問題是**每一條路由**該用哪種。這個站用 Nuxt 的 routeRules 混搭三種策略，值得把決策過程記下來。\n\n## 三種模式，三種取捨\n\n- **prerender（SSG）**：build 時生一次 HTML。最快、最省，但內容凍結在 build 那一刻——連 build 當下 API 掛掉都會凍出一頁空列表。適合首頁、關於頁這種改版才變的頁。\n- **swr（自架版 ISR）**：第一次請求時 SSR，把 HTML 快取 N 秒；過期後**先回舊的**、背景重生。讀者永遠拿到即時回應，內容最多舊 N 秒。筆記列表與內文都用它（60 秒）。\n- **純 SSR**：每次請求都算。這個站沒有頁面需要——這也是重點，**預設不該是它**。\n\n```ts [nuxt.config.ts]\nrouteRules: {\n  '\u002F':            { prerender: true },\n  '\u002Fgarden':      { swr: 60 },\n  '\u002Fgarden\u002F**':   { swr: 60 },\n  '\u002Fsitemap.xml': { swr: 600 },\n}\n```\n\n一個部署現實：nitro 的 `isr` 規則只在 Vercel\u002FNetlify 生效，自己架 node-server 時 `swr` 才是可攜的等價物。\n\n## swr 的連鎖效應：活資料要分流\n\nHTML 被快取 60 秒，代表**頁面裡的即時數字不能烤進 HTML**。到訪計數、澆灌數這些活資料一律 client 端另外抓，SSR 的佔位用固定尺寸撐住（零 CLS）。瀏覽計數也因此必須是 client beacon——swr 命中時根本不會有請求打到 API，伺服器端計數永遠低估。\n\n## SSR 的隱形身分：它是你的頭號 API 消費者\n\nSSR 伺服器打 API 用的是**伺服器自己的 IP**——所有訪客的首次載入共用同一個來源。這件事在限流上炸出過一場[[throttle-429-404|429 誤報 404 的慘案]]，教訓是：設計 API 限流時，SSR 不是一個普通用戶，它是站在你家門口的巨人。","「SSR 還是 SSG？」是個假問題——正確的問題是每一條路由該用哪種。這個站用 Nuxt 的 routeRules 混搭三種策略，值得把決策過程記下來。 三種模式，三種取捨 - prerender（SSG）：build 時生一次 HTML。最快、最省，但內容凍結在 build 那一刻——連 build 當下 API …",[9,10,11],"nuxt","ssr","seo","evergreen",null,"2026-07-14T06:54:19.022Z","2026-07-14T11:26:32.481Z",true,{"throttle-429-404":18},"一場 429 假扮 404 的偵探記：限流的讀寫分道",[20,23,26],{"slug":21,"title":18,"maturity":22},"throttle-429-404","budding",{"slug":24,"title":25,"maturity":22},"code-use-note-stats","程式碼走讀：一個 composable 裡的樂觀更新與回滾",{"slug":27,"title":28,"maturity":12},"rootnote-origin","Rootnote：這座花園本身就是一件作品","AI助理"]