Ian Chou's Blog

從 R2 架構的大夢初醒:為什麼我放棄統一 CMS,轉向「多重子網域」的聯邦式架構

Title: From Over-Engineering to Shipping: Why I Ditched the Unified CMS for a "Federated" Multi-Repo Architecture

前言:工程師的通病

我們都知道那個故事:一個工程師想寫部落格,於是他花了一個月挑選框架,兩個月設計架構,三個月優化 CI/CD,最後……他一篇文章都沒寫。

我最近就差點掉進這個坑裡。

作為一名追求技術極致的開發者,我原本構想了一個完美的架構:Astro MPA (SSR) + Cloudflare R2。我希望能將「引擎」與「內容」完全分離,把 10GB 的文章存在 R2 物件儲存中,透過動態渲染來繞過 Build Time 的限制。這聽起來很性感,很 Enterprise,技術含金量很高。

但現實狠狠打了我的臉。我發現我把 90% 的時間花在處理 API 串接、快取策略、資料同步和權限管理,只有 10% 的時間在產出內容。

這條路太累了,而且產出極低。 於是我做了一個大膽的決定:砍掉重練。

為什麼「統一架構」在個人專案是個陷阱?

在上一版的設計中,我試圖解決的問題是:

  1. 內容庫過大 (10GB):導致 Static Site Generation (SSG) 建置超時。
  2. 內容壽命長:包含了十幾年前的舊資料。

使用 R2 + SSR 確實解決了技術限制,但引入了巨大的維護成本:

我意識到,我不需要一個「完美的 CMS」,我需要的是一個「能讓我馬上寫作,且未來能隨意更換技術棧」的方案。

新方案:多 Repo + 多子網域的「聯邦式」架構

我決定採用 「分而治之 (Divide and Conquer)」 的策略。

既然單一 Repo 太大,那就把它切開。既然統一技術棧很難維護,那就允許不同時期的網站使用不同的技術。

我將部落格拆解為多個獨立的 Git Repository,每個 Repo 對應一個 「特定的時間區段」「特定的技術棧」,並部署在 Cloudflare Pages 上的不同子網域。

我的命名哲學:{Stack}{Year}{Batch}.citrine.top

這是我目前採用的命名規則,它極具彈性:

子網域前綴 技術棧 (Stack) 年份 (Year) 批次 (Batch) 完整網域範例
n25a Next.js 2025 A n25a.citrine.top
e25b Eleventy 2025 B e25b.citrine.top
a24c Astro 2024 C a24c.citrine.top

這個架構的巨大優勢

1. 技術棧自由 (Tech Stack Agnostic)
這是我最喜歡的一點。

2. 完美的 Cloudflare Pages 適配性
Cloudflare Pages 的計費和限制是針對「每個專案」的。

3. 隔離風險
如果我在 n25a 寫了一段爛 Code 把網站弄掛了,a24c 的舊文章完全不受影響。每個時期的網站都是獨立的「時空膠囊」。

實作細節

我的主網域 citrine.top 現在只作為一個 「入口大廳 (Landing Page)」

結語:Shipping is all that matters

MPA + R2Multi-Repo + Subdomains,我學到最重要的一課是:

不要為了 1% 的極端情況,去犧牲 99% 的開發體驗。

雖然 R2 架構在技術上是「正確」且「可擴展」的,但它阻礙了我「發布內容」這個核心目標。現在的架構雖然看起來有點「散」,但它極度簡單、成本極低,而且最重要的是——它讓我重新找回了寫 code 和寫文章的樂趣。

現在,不管我想用 Next.js、Eleventy 還是 Astro,我只要 git init,然後開始寫作。

這才是個人開發者該有的自由。