快轉到主要內容

用 Cloudflare Pages 免費託管私有庫的靜態網站

·1791 字· loading · loading ·
目錄
GitHub Pages 免費方案不支援私有庫,改用 Cloudflare Pages 在雲端建置並發布,原始碼不必公開。

為什麼用 Cloudflare Pages
#

GitHub Pages 的免費方案要求「儲存庫必須是公開的」。如果不想公開原始碼,可以改用 Cloudflare Pages:它用自己的 GitHub App 讀取儲存庫(公開或私有都行),在雲端幫你建置後發布到邊緣網路,一樣免費。

私有庫透過 Cloudflare Pages 建置並發布的流程
私有庫透過 Cloudflare Pages 建置並發布的流程

Cloudflare Pages 會讀取專案根目錄的 wrangler.jsonc,其中 assets 區塊負責靜態檔;需要時還能加一段在邊緣執行的程式碼(見文末「Worker 能做的事」)。

本文假設你已經有一個能正常 hugo --gc --minify 的專案(建站流程見「如何使用 Hugo 架設部落格並部署到 GitHub Pages?」),並已推到一個私有的 GitHub 儲存庫。


設定 wrangler
#

在專案根目錄放一個 wrangler.jsonc,最單純的純靜態設定如下:

1{
2  "name": "my-blog",
3  "compatibility_date": "2026-09-05",
4  "build": { "command": "./build.sh" },
5  "assets": {
6    "directory": "./public",
7    "not_found_handling": "404-page"
8  }
9}
  • compatibility_date:鎖定 Workers runtime 的行為版本。Cloudflare 之後若調整 runtime 的預設行為,你的專案仍會依照這個日期當天的規則執行,不會因平台更新而壞掉。設為建立專案當天的日期即可,日後想採用新行為再往後調。
  • build.command:Cloudflare Pages 建置時執行的指令,這裡交給一支 build.sh
  • assets.directory:靜態檔目錄,也就是 Hugo 的 public/
  • not_found_handling:找不到路徑時回傳 public/404.html

build.sh 負責在雲端環境把 Hugo(與主題需要的 Go)裝好再建置。版本在這裡固定住,確保每次建置一致:

 1#!/usr/bin/env bash
 2set -euo pipefail
 3
 4# 固定版本,確保雲端每次建置結果一致;記得定期更新
 5HUGO_VERSION=0.166.0
 6GO_VERSION=1.27.0
 7export HUGO_CACHEDIR="${PWD}/.cache/hugo"
 8
 9mkdir -p "${HOME}/.local"
10
11# 主題用 Hugo Module 時才需要 Go
12if [[ -f go.mod ]]; then
13  curl -sfL "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar -C "${HOME}/.local" -xz
14  export PATH="${HOME}/.local/go/bin:${PATH}"
15fi
16
17curl -sfL "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz" \
18  | tar -C "${HOME}/.local" -xz hugo
19export PATH="${HOME}/.local:${PATH}"
20
21hugo --gc --minify

本機測試與手動部署:

1npm install -D wrangler
2npx wrangler login    # 首次需要授權
3npx wrangler dev      # 本機模擬邊緣環境
4npx wrangler deploy   # 手動部署

從 Cloudflare Pages 接上 GitHub
#

接上 Git 之後,每次 push 就會自動建置並部署,不必手動跑 wrangler deploy

Cloudflare Dashboard > Compute > Workers & Pages > Create application > 選 Connect with GitHub(或其他你自訂的空間),接著找到 Repository 連結過去。

如果沒看到 Repository,則可能是 GitHub 那尚未授權給 Cloudflare,透過 GitHub 的 Settings > Applications > Cloudflare Workers and Pages > 點擊 Configure 即可編輯授權。

權限設定 Read-Only 即可:

Github 設定欲授權給 Cloudflare 之 Repository 的權限
Github 設定欲授權給 Cloudflare 之 Repository 的權限

可以選擇全部授權或單獨授權,建議後者:

Github 選擇欲授權給 Cloudflare 的 Repository
Github 選擇欲授權給 Cloudflare 的 Repository

  • 建置設定:Cloudflare Pages 會讀取 wrangler.jsonc,把 Build command 設為 ./build.sh(若沒用 build.sh,就直接填 hugo --gc --minify)。
  • 若沒有用 build.sh 自己裝 Hugo,就在 Variables and Secrets 加環境變數指定版本:
1HUGO_VERSION = 0.166.0

(主題需要 Go 時,專案裡有 go.mod,Cloudflare Pages 會自動裝 Go,也可另外設 GO_VERSION

  • Save and Deploy,完成後會得到一個 <專案名>.<子網域>.workers.dev 網址。在該專案的 Settings > Domains & Routes 加入自己的網域,Cloudflare Pages 會自動簽發憑證。網域的 DNS 若也在 Cloudflare,整個過程非常簡便。

順便一提:Worker 能做的事
#

靜態託管只是最基本的用法。在 wrangler.jsonc 加一個 main 指向的腳本,就能在請求進出時插一段程式碼,靜態檔則透過 ASSETS 綁定取得:

 1{
 2  "name": "my-blog",
 3  "main": "src/index.js",
 4  "compatibility_date": "2026-09-05",
 5  "build": { "command": "./build.sh" },
 6  "assets": {
 7    "directory": "./public",
 8    "binding": "ASSETS",
 9    "not_found_handling": "404-page"
10  }
11}
 1// src/index.js:幫每個回應補上安全性標頭
 2export default {
 3  async fetch(request, env) {
 4    const res = await env.ASSETS.fetch(request);
 5    const out = new Response(res.body, res);
 6    out.headers.set("X-Content-Type-Options", "nosniff");
 7    out.headers.set("Referrer-Policy", "strict-origin-when-cross-origin");
 8    return out;
 9  },
10};

常見用途:自訂 HTTP 標頭與快取策略、舊網址轉址、依國家或裝置回傳不同內容、用 Basic Auth 擋住尚未公開的預覽站、反向代理 API 以避開 CORS。


References
#

Alpaca
作者
Alpaca
No one can stop my feet.

相關文章