以 Astro 正式建置產物啟動本機 Wrangler 後,請求 /blog 會先得到 307 Temporary Redirect,跟隨到 /blog/ 才是 200。本文的實測範圍是本機 Wrangler 4.125.0;正式網域部署後仍要再讀回確認。

原因很單純:導覽列的連結寫的是 /blog(沒有尾斜線),而建置產物是 blog/index.html。靜態資產伺服器的 HTML handling 在預設的 auto-trailing-slash 模式下,會把 /blog 轉向到 /blog/。

值得記下來的是轉址的狀態碼。Cloudflare 官方 HTML handling 文件也把 /folder 到 /folder/ 列為 307;切成 force-trailing-slash 同樣使用 307。 這和永久轉址的語意不同:

  • Google 的文件說明,暫時轉址本身不作為把目的地選為 canonical 的訊號; 其他 canonical 訊號仍可能讓目的地被索引。因此不能把 307 解讀成「搜尋引擎一定不會合併」。
  • 當瀏覽器需要向伺服器取得這個轉址時,載入正文前會多一次請求。 實際延遲取決於網路與快取條件;站內連結直接指向最終 URL,就能避免這段不必要的路徑。

修法有兩半,缺一不可:

  1. astro.config.mjs 設 trailingSlash: 'always',讓路由產生器輸出的每一個 URL 都帶尾斜線——這一步同時決定了 paginate() 產出的分頁 URL 形狀。
  2. 把站內硬編的連結改成帶尾斜線的形式。設定管不到手寫的 href。

無斜線形式的收斂則交給 wrangler.jsonc 的 assets.html_handling: "force-trailing-slash"——它只作用於 HTML 請求, 不會動到 .xml、favicon 或 /_astro/* 的雜湊資產。

我把這件事收進 HTTP smoke:無斜線 URL 應回 307,目的地直接回 200;站內連結、 canonical、RSS 與 sitemap 則直接使用有斜線的 URL。平台的自動正規化仍保留, 讀者從站內導航時已經走最短路徑。

參考資料