雲端架構

用 AWS 架靜態網站,一個月實際要多少錢

發佈於 2026-08-13 .約 9 分鐘閱讀

我目前有十個網站跑在 S3 + CloudFront 上。這篇把實際的帳單拆開來講,順便講三個我踩過、會讓帳單暴增的坑。

先講結論

一個每月 5 萬次瀏覽、傳輸 20GB 的靜態網站,AWS 的費用大約是每月 1.7 到 2.5 美元

其中 CloudFront 的流量費是主要成本,S3 的儲存費幾乎可以忽略。真正的固定成本反而是網域(每年約 12 美元)與 Route 53 託管區(每月 0.5 美元)。

帳單拆解

以我其中一個站台上個月的實際數字為例:

項目用量費用(USD)
S3 標準儲存240 MB0.006
S3 PUT 請求3,100 次(部署 sync)0.016
S3 GET 請求8,400 次0.003
CloudFront 流量傳出19.2 GB1.63
CloudFront HTTP 請求412,000 次0.41
CloudFront Function412,000 次0.04
Route 53 託管區1 個0.50
Route 53 查詢180 萬次0.72
合計約 3.33

有幾件事值得注意。

第一,Route 53 佔了 1.22 美元,超過三分之一。 這是很多人沒預期到的。託管區本身每月 0.5 美元是固定的,跟流量無關;查詢費則會隨流量成長。如果你有十個網域,光託管區就是每月 5 美元。

第二,CloudFront 請求數的費用不可忽視。 41 萬次請求收 0.41 美元。一個頁面如果載入 30 個資源,5 萬次瀏覽就是 150 萬次請求。減少請求數 = 直接省錢,而且它同時也讓網站更快。

第三,S3 的部分幾乎是零。 240MB 的靜態檔案,儲存費不到一美分。所以不要為了省 S3 空間而壓縮圖片壓到畫質變差——那個方向省不到錢。

免費額度的真正邊界

AWS 的免費額度有兩種,很多人搞混:

十二個月免費額度(只有新帳號的前一年):S3 5GB 儲存、2 萬次 GET、2 千次 PUT。

永久免費額度(所有帳號都有):CloudFront 每月 1TB 傳出、1000 萬次 HTTP 請求、200 萬次 CloudFront Function 呼叫。

第二項才是重點。CloudFront 的永久免費額度非常大方——每月 1TB 流量,對絕大多數個人網站來說根本用不完。上面那張帳單其實有一大部分是被免費額度吸收掉的。

換句話說,一個中小型的靜態網站,實際上很可能只需要付 Route 53 的錢。

三個會讓帳單暴增的陷阱

陷阱一:Cache-Control 沒設好

如果你的 HTML 和資源檔案都沒有設 Cache-Control,CloudFront 的預設 TTL 只有 24 小時,而瀏覽器可能完全不快取。結果是每個回訪的使用者都重新下載一次全部資源。

正確的做法是把檔案分成兩類:

# 帶 hash 的資源檔:長期快取
aws s3 sync ./dist s3://bucket \
  --exclude "*.html" \
  --cache-control "public,max-age=31536000,immutable"

# HTML:不快取,每次都驗證
aws s3 sync ./dist s3://bucket \
  --exclude "*" --include "*.html" \
  --cache-control "public,max-age=0,must-revalidate"

帶內容 hash 的檔名(app.a3f9c2.js)可以安全地設一年,因為內容變了檔名就會變。HTML 則必須每次驗證,否則使用者會拿到舊版。

這一項設好之後,我某個站的流量費降了約 40%。

陷阱二:無節制的 Invalidation

CloudFront 的快取失效,每月前 1000 個路徑免費,超過的部分每個路徑 0.005 美元。

聽起來很便宜,但如果你的部署腳本寫 --paths "/*",那每次部署算一個路徑——這其實很划算。真正的問題是相反的寫法:有人為了「精確」而列出全部 300 個檔案路徑,一天部署五次,一個月就是 45,000 個路徑,收費 220 美元。

規則很簡單:要嘛用 /*,要嘛只列真的必要的少數幾個。 不要列出全部檔案。

陷阱三:S3 bucket 被公開直連

如果你的 S3 bucket 設成公開讀取,而有人(或搜尋引擎)直接抓 S3 的網址而不是 CloudFront 的網址,那些流量就完全不受 CloudFront 免費額度保護,而且 S3 的流量費比 CloudFront 貴。

解法是使用 Origin Access Control(OAC):bucket 完全封閉,只允許 CloudFront 存取。

BlockPublicAccess: BLOCK_ALL
Origin: S3BucketOrigin.withOriginAccessControl(bucket)

這同時也是安全上的正確做法。

靜態網站的一個常見坑:路徑改寫

用 S3 當來源有一個煩人的行為:它不會自動補 index.html

/guides/ 這個路徑,瀏覽器要的是 guides/index.html,但 S3 只會去找一個叫 guides/ 的物件,然後回 403。

解法是加一個 CloudFront Function(viewer request 階段):

function handler(event) {
  var request = event.request;
  var uri = request.uri;
  if (uri.endsWith("/")) {
    request.uri += "index.html";
  } else if (!uri.includes(".")) {
    request.uri += "/index.html";
  }
  return request;
}

CloudFront Function 每百萬次呼叫 0.10 美元,而且有每月 200 萬次的永久免費額度,成本可以忽略。

順帶一提:不要用「404 導向 index.html」來處理這件事。那是 SPA 的做法,會讓所有不存在的路徑都回傳 200,搜尋引擎會判定為 soft 404,對 SEO 有實質傷害。靜態網站應該讓 404 就是 404。

什麼時候不該用這個架構

講了這麼多好處,也要講界線。這個架構不適合:

  • 需要伺服器端渲染個人化內容的網站。 每個使用者看到的頁面都不同時,CDN 快取的價值就消失了。
  • 內容更新極為頻繁的網站。 每分鐘都要更新的話,快取失效的管理會變成負擔。
  • 需要複雜後端邏輯的應用。 那應該是 Lambda 或容器的工作,靜態站只負責前端。

但如果你的網站是產品頁、文件、部落格、作品集——也就是大多數網站——這個架構在成本、速度與維運負擔上都很難被超越。每月三美元、全球 CDN、沒有伺服器要管,這個組合在十年前是不存在的。

其他文章

回到文章列表 →

內容有錯誤或想補充?寄信到 support@throuzlabs.com, 我會更新並在文中註明修訂日期。