在 Cloudflare Pages 部署 Astro 5:三個你需要調整的預設
Astro 5 在 Cloudflare Pages 上跑得很順,但有幾個預設值跟邊緣 CDN 哲學不太合拍。本文整理我在 elongma.tech 改版過程中踩到的三個小坑與解法。
- #Astro
- #Cloudflare Pages
- #DevOps
- #靜態網站
本文作者背景:SRE / DevOps 工程師,目前以 Astro 5 + Cloudflare Pages 維運自家技術網站 elongma.tech。
Astro 5 的 zero-JS-by-default 與 Cloudflare Pages 的免費邊緣 CDN 是個甜蜜組合。但實際把網站丟上去之後,會發現幾個預設值還沒被討論透徹,這篇整理我自己在生產環境踩到的三個。
一、Sitemap 用 sitemap-index.xml 而不是 sitemap.xml
@astrojs/sitemap 的預設輸出是兩個檔案:
dist/
├── sitemap-index.xml ← 索引檔
└── sitemap-0.xml ← 實際 URL 列表
而不是大家直覺以為的 sitemap.xml。如果你的 robots.txt 還寫著:
Sitemap: https://your-site/sitemap.xml
Google Search Console 會告訴你 sitemap 不存在但實際上是路徑寫錯。修正:
Sitemap: https://your-site/sitemap-index.xml
或在 astro.config.mjs 裡用 customPages 與 serialize 客製化輸出單一 sitemap.xml,但通常索引檔模式對未來擴充(多語、子網域)更彈性,直接改 robots.txt 是更省事的選擇。
二、og:locale 必須是底線格式 zh_TW,不是連字符 zh-TW
HTML lang 屬性用 BCP 47 格式(zh-TW),但 Open Graph protocol 規定 locale 用底線(zh_TW)。如果你直接複用:
<html lang={siteConfig.lang}>
...
<meta property="og:locale" content={siteConfig.lang} /> ❌
Facebook / LinkedIn 的 OG debugger 會出 warning「locale not recognized」。修法:
<meta property="og:locale" content={siteConfig.lang.replace('-', '_')} />
一行解決。Twitter 不吃 og:locale,所以 Twitter 端不需處理。
三、Astro Image Optimization 在 CF Pages 純靜態模式下會跑 build-time 處理
Astro 5 的 astro:assets 預設在 build time 處理圖片(產出 WebP/AVIF + 多 size),這在 Cloudflare Pages 純靜態部署下是期望行為,但有兩個副作用:
-
build 時間變長:每張圖會生成 3-5 個變體
-
sharp是必要依賴,但pnpm預設不執行其 build script,會看到:Ignored build scripts: esbuild, sharp. Run "pnpm approve-builds" to pick which dependencies should be allowed to run scripts.如果不批准,sharp 會 fallback 到較慢的 squoosh,build 會變更慢且部分圖片格式不支援。
修法:
pnpm approve-builds
選擇 sharp 與 esbuild 允許執行。CI/CD 環境可以在 package.json 加 pnpm.onlyBuiltDependencies:
{
"pnpm": {
"onlyBuiltDependencies": ["esbuild", "sharp"]
}
}
這樣 CF Pages 的 build 環境會自動處理。
結語
這三個坑都不是 bug,只是預設值針對的是「最大公約數」的使用情境。Cloudflare Pages 的「全球邊緣 + 純靜態」是現代個人 / 中小企業網站的甜蜜點,但魔鬼還是藏在 meta tag 與 build pipeline 的小細節裡。
下一篇我會寫個人接案者的最小可行 SRE:用 GitHub Actions + Cloudflare 自動化的工作流,敬請期待。