為什麼這個部落格跑在 Cloudflare 上

Astro 靜態輸出、Workers 與 D1 的分工,以及一個月零元的理由。

這個網站的核心問題很簡單:文章是靜態的,但留言不是。

如果把整站做成純靜態,留言就得另外找服務;如果做成全動態,又會為了几則留言讓每一篇文章都經過伺服器。最後我選擇把兩者拆開:

Markdown → Astro build → dist/ → Workers Static Assets
                                      └── /api/* → Worker → D1

靜態的部分

文章放在 src/content/blog/,用 Astro 的 content collections 管理。建置時會產生:

  • 文章列表與文章頁
  • 標籤頁
  • RSS 與 sitemap
  • 404 頁面

這些全部是 HTML,直接由 Cloudflare 的靜態資產服務送出。依照 Cloudflare 的計價方式,靜態資產的請求是免費且無限的,所以就算文章被大量轉載,也不會因為流量而產生帳單。

動態的部分

只有兩個 API 需要 Worker:

端點 用途 儲存
/api/views/[slug] 瀏覽次數 D1 page_views
/api/comments/[slug] 留言讀取與寫入 D1 comments

留言寫入前會經過 Turnstile 驗證,另外用 HMAC 處理過的 IP 做短期頻率限制。資料庫裡不存原始 IP,只存雜湊值。

成本

以個人部落格的規模來說:

  • Workers Free:每天 10 萬次動態請求,靜態請求不計入
  • D1 Free:每天 500 萬列讀取、10 萬列寫入、5 GB 儲存
  • R2 Free:10 GB 儲存(如果之後要放原圖)
  • 網域:每年約 10 美元

換句話說,沒有意外的話,每月成本是 0 元。真的有一天流量大到超過免費額度,Workers Paid 也是每月 5 美元起。

為什麼不直接用 Pages

Cloudflare 現在建議新專案使用 Workers 與 Static Assets;Pages 仍然可用,但主要是既有專案在維護。這個網站從第一天就用 Workers,未來要加 Durable Objects、Queues 或 Cron,也不需要搬家。

一個小提醒

如果主要讀者在中國大陸,Cloudflare 免費方案在當地的連線品質並不穩定。這是選型時就應該知道的事,而不是等網站上線後才發現。