跳至主要內容
Cloudflare Deployment

從 Pages 到 Workers — SuperPortia 的 Cloudflare 部署演化

3 分

SuperPortia 在 Cloudflare 上跑著 4 個靜態站、3 個 Worker、以及 D1 + Vectorize 儲存層。月費:$0。這篇文章記錄這套架構是怎麼長出來的,以及 Astro 被 Cloudflare 收購之後,新專案的部署方式發生了什麼變化。

全景:今天的狀態

registry.json 可以數出三種部署在 Cloudflare 上的模式:

cloud-serverless(Workers):

  • Cloud UB Worker — 知識 API,ub.superportia.dev
  • Email Intake Worker — Gmail 輪詢 + AI 分類,cron every 3 min
  • Scout Worker — 定時情報收集,scout.superportia.dev

local-build-cloud(需本地建置後部署):

  • Bridge — Next.js 15,OpenNext → Cloudflare Pages,bridge.superportia.dev
  • Reading — Astro SSR,@astrojs/cloudflare adapter → Workers,read.superportia.dev

cloud-static(Pages auto-deploy):

  • Docs Site — Docusaurus,docs.superportia.dev
  • Blog — blog.superportia.dev
  • Catmints Cafe — 靜態 HTML,cafe.superportia.dev

儲存層橫跨多個 Worker 共用:D1 SQL 資料庫、Vectorize 向量索引、Workers AI(embedding 生成)。

這個組合在 Cloudflare 的免費層上完全跑得起來——後面的章節會把具體額度列出來。

Pages vs Workers:Astro 收購改變了預設答案

SuperPortia 的早期靜態站全部部署在 Cloudflare Pages。Pages 提供 Git 連接、自動建置、免費 CDN,是當時最省事的選擇。Workers 則用於後端邏輯,例如最早期的 UB API。

這個局面在 2026 年 1 月發生了根本性的轉變。

2026-01-16,Cloudflare 宣布收購 Astro。@astrojs/cloudflare adapter 隨後更新,預設部署目標從 Pages 改為 Workers。執行 astro add cloudflare 時,產生的是 wrangler.jsonc + Workers 設定,而不是以前的 Pages 設定。

官方立場很清楚:Cloudflare 建議新專案使用 Workers,Pages 是遺留介面。

為什麼 Workers 比 Pages 更好?

面向PagesWorkers
儲存 binding有限制完整支援 D1、KV、R2、Vectorize、Queues、Durable Objects
請求處理靜態 CDN 為主完整 middleware、caching 策略、edge compute
本地開發Node.js 模擬真實 workerd runtime,dev 和 prod 行為一致
部署指令wrangler pages deploywrangler deploy(更快更簡潔)
未來投資方向維護模式Cloudflare 主要開發投入

對 SuperPortia 的新 Astro 6 專案(Reading、Agentic、未來的 UB Dashboard),結論是明確的:Workers

現有的 Bridge 和靜態站則繼續留在 Pages,直到有足夠的理由遷移為止。Bridge 使用 Next.js 15 而非 Astro,這個轉變不直接影響它。

Workers 實際長什麼樣:Cloud UB 的架構

Cloud UB Worker 是 SuperPortia 最複雜的 Worker,也是理解整體架構的最好案例。

wrangler.toml 的實際內容:

name = "superportia-ub"
main = "worker.js"
compatibility_date = "2025-01-01"
workers_dev = true

[[d1_databases]]
binding = "DB"
database_name = "superportia-ub"
database_id = "166954b9-e07e-4911-8aeb-d783a7f792d0"

[ai]
binding = "AI"

[[vectorize]]
binding = "VECTORIZE"
index_name = "superportia-ub-vectors"

三個 binding 在一個 Worker 裡:

  • DB → D1 SQLite,存放 entries(UB Dock 碼頭)、classified_entries(正區)、email_intel
  • AI → Workers AI binding(@cf/... 模型);實際 embedding 用 gemini-embedding-001(Google API,透過 fetch 呼叫,非 [ai] binding 直接掛載的模型)做 768 維向量
  • VECTORIZE → Vectorize 索引,做語義搜尋

自訂域名 ub.superportia.dev 透過 CF Dashboard 設定(DNS + SSL 自動處理),不需要寫進 wrangler.toml

Email Intake Worker 的架構更單純——它只有 cron handler,沒有 HTTP routing。*/3 * * * * 每三分鐘執行一次,輪詢 Gmail API、AI 分類、寫入 email_intel 表。對外只有 superportia-email-intake.wishia.workers.dev,但實際上從不處理入站 HTTP 請求。

部署方式:wrangler、GitHub Actions、自動部署

SuperPortia 使用三種部署路徑,對應不同場景:

1. wrangler deploy(本地直接部署)

適合快速迭代或一次性部署:

# 設定好環境變數後直接執行
wrangler deploy

CLOUDFLARE_API_TOKENCLOUDFLARE_ACCOUNT_ID~/.zshenv 自動載入。

2. GitHub Actions + cloudflare/wrangler-action

Cloud UB Worker 走這條路:推送到 main,GitHub Actions 自動執行 wrangler deploy。需要在 repo 設定兩個 Secrets:CLOUDFLARE_API_TOKENCLOUDFLARE_ACCOUNT_ID

對生產服務而言,這是正確的模式——每次 push 有完整的 CI log,可審計、可回溯。

3. Cloudflare Pages auto-deploy(Git 連接)

Docs Site、Catmints Cafe、Blog 使用這條路。在 CF Dashboard 連接 GitHub repo,設定建置指令,之後每次 push 到 main 自動建置部署。最省事,但僅適合靜態站。

deploy-gate hook

Ops repo 有一個 pre-commit hook,防止意外部署。任何包含 wrangler deploy 或影響生產設定的變更,都需要明確確認才能執行。這個 gate 在多次 SSH session 遠端操作中避免了誤觸部署。

免費層現實:$0/month 能跑什麼

這是最常被問到的問題。以下是 Cloudflare 免費層的實際額度,以及 SuperPortia 目前的用量情況:

服務免費額度SuperPortia 用量
Workers100,000 req/dayUB API + Email Intake + Scout,日流量遠低於上限
D15 GB storage,5M rows read/dayUB entries + email_intel,目前數百 MB
Vectorize5M vectors,30M dimensions queried/dayUB vectors,目前數萬筆
Workers AI有每日 neurons 限制Embedding 生成,每次 ingest 用一次
Pages無限靜態站,500 builds/month4 個靜態站,deploy 頻率低
R210 GB storage,1M Class A ops/month目前未啟用,規劃作圖片儲存
CF Tunnel免費(cloudflared)SiYuan Notes 透過 tunnel 對外

實際上,Workers AI 的 neurons 限制是最可能碰到天花板的地方(若使用 @cf/... 模型)。每次 ingest_fragment 呼叫都會用 gemini-embedding-001(透過 Google API fetch)生成一個 768 維向量。如果某天大量 batch ingest,Workers AI 可能會被限速。目前的因應方式是 MTAAA pipeline 的 boiler_grandpa_v2.py 分批執行,避免單次 burst。

D1 的 5GB 免費額度對知識庫來說非常充裕。SQLite 格式壓縮效率高,UB 的 entries + classified_entries 即使成長到數十萬筆也不會超過上限。

遷移路線:哪些留 Pages,哪些移 Workers

基於目前的架構和 Cloudflare 的發展方向,SuperPortia 的遷移策略如下:

繼續留在 Pages(有原因才遷移):

  • Bridge — Next.js 15,OpenNext 對 CF Pages 支援成熟,遷移收益小
  • Docs Site / Blog / Catmints Cafe — 純靜態,Pages 完全夠用,auto-deploy 省事

已在 Workers(正確位置):

  • Cloud UB Worker、Email Intake、Scout Worker — 這三個本來就只能是 Workers

新專案預設 Workers:

  • Reading — 已是 Astro SSR on Workers
  • Agentic(v2)— 開發中,將部署 Workers
  • UB Dashboard(計劃中)— Astro 6 on Workers,可用 D1 native binding 直接讀 UB 資料

一個值得注意的細節:Astro 6 的 @astrojs/cloudflare adapter 現在使用真實的 workerd runtime 跑本地開發,這意味著 D1 binding 在 wrangler dev 階段就能連到 remote D1,和生產行為一致。舊的 Pages 路徑依賴 Node.js 模擬,有時在生產才發現 runtime 不相容的問題。Workers 路徑在開發階段就把這個坑填掉了。

為什麼沒有使用自己的伺服器

一個自然的問題:為什麼不在自己的 VPS 或 NAS 上跑這些服務?

幾個具體原因:

零冷啟動:Workers 在 Cloudflare 全球 300+ 個資料中心執行,沒有傳統 serverless 的冷啟動問題。UB API 的 p99 latency 穩定,不像 Lambda 或 Cloud Functions 那樣有首次喚醒延遲。

綁定生態:D1、Vectorize、KV、R2 作為 binding 直接掛載在 Worker 裡,不需要網路往返。UB Worker 查詢 D1 和 Vectorize 是同一個 runtime 內的 binding 呼叫,延遲比任何外部資料庫都低。

維運成本:在 $0/month 的條件下,不需要管理 OS 更新、SSL 憑證、反向代理設定、監控告警基礎設施。這些維運工作時間比技術工作還貴。

對 SuperPortia 這種規模(個人 + 小團隊),Cloudflare Workers 的免費層覆蓋了幾乎所有生產流量,這不是暫時的設計——而是長期的架構選擇。

小結

Pages 是起點,Workers 是方向。這個轉變不是為了趕上新技術,而是因為 Cloudflare 把它的整個儲存 + 計算生態都綁在 Workers 上。

SuperPortia 的部署現況:

  • 3 個 Workers 提供後端 API 和排程工作
  • 4 個 Pages 站點提供靜態前端
  • D1 + Vectorize 提供持久儲存,全部在免費層內
  • 新 Astro 6 專案直接走 Workers,不再走 Pages

完整的部署類型說明見 SuperPortia 專案全景 — 29 個專案,3 個維度,Cloud UB 的知識架構(Dock → 正區 雙表設計)見 Cloud UB 相關文章。

...強可用要好得多。 Phase 0 的降規,表面上看是退步,實際上是建立一個可以信任的基礎。一個 score → compare → revert/keep 的最小閉環,比一個充滿假設但從未穩定運行的複雜閉環,有價值一百倍。 我們從四層審查出發,走回了工程的第一原則:先讓它跑得通,再讓它跑得好,最後才讓它跑得快。 相關文章:[[Beast Mode + autoResearch 完整指南]] |...

在此文章中被引用

...k(entries table)後, 的分類管線自動接手分類和提升到正區(classified_entries)。 詳細的 UB 架構可以從這篇了解背景:[[從 Pages 到 Workers — SuperPortia 的 Cloudflare 部署演化]]。 這個場景替代了人工 RSS 閱讀 SuperPortia 每天大概有...

在此文章中被引用