AstroをCloudflare Pagesで再読み込みすると404になるときの確認順

AstroのページをCloudflare Pagesで直接開く、または再読み込みすると404になる問題を、生成済みHTML、動的ルート、末尾スラッシュ、リダイレクト、SPA設定の順に切り分けます。

AstroをCloudflare Pagesへ公開したあと、サイト内リンクでは開けるのに、URLを直接開くか再読み込みすると404になることがあります。キャッシュと決めつけず、要求URLに対応するHTMLがビルド成果物にあるかから調べるのが近道です。

ここではAstroの静的出力をPagesへ配信する構成を前提に確認順を整理します。配信構成から見直す場合はAstroをCloudflare Pagesへデプロイする手順を先に確認してください。

404が起きるURLを分ける

トップ/、対象の/kiji/example/、末尾の/を外した形、存在しないURLを新しいタブで開き、直接表示と再読み込みのHTTP状態を記録します。

トップまで404なら、出力先かindex.htmlの欠落を疑います。Cloudflare公式も、pages.devのルートが404ならindex.htmlがない可能性を挙げています。特定ページだけなら、生成漏れ、URL表記、転送設定の順で絞ります。開発者ツールのNetwork欄やcurl -I 対象URLでHTTP状態も確認します。

症状と最初に見る場所

症状最初に見る場所期待する状態
トップ/も404配信先直下のindex.htmldist/index.htmlがあり、トップが200
特定の記事だけ404dist内の該当HTMLとgetStaticPaths()URLに対応するHTMLが生成済み
/page/page/の片方だけ404trailingSlash、リンク、転送規則正規URLが200、もう片方は必要に応じて転送
すべての未知URLがトップを表示直下の404.htmlとSPA設定静的記事サイトでは未知URLが404
_redirectsが効かないPages Functionsの対象ルートFunctionと静的転送の担当が重複していない

静的出力にページがあるか確認する

Astroのoutput: 'static'はビルド時にHTMLを生成します。/kiji/example/を公開するなら、一般的な出力先には次のファイルが必要です。

dist/
├─ index.html
├─ 404.html
└─ kiji/example/index.html

該当HTMLがなければ、Cloudflareの設定を変えてもページは出ません。先に生成処理を直します。ファイルがあるなら、Pagesの出力先がdistか、古い別フォルダーを配信していないかを確認します。開発サーバーでの成功だけを根拠にせず、本番と同じ成果物を見ます。

動的ルートの生成結果を見る

src/pages/kiji/[...id].astroのような動的ルートは、静的モードではURL一覧をビルド時に確定させます。Astro公式によると、getStaticPaths()から各パスのparamsを返す必要があります。

export async function getStaticPaths() {
  const articles = await getCollection('articles');
  return articles.map((article) => ({
    params: { id: article.id },
    props: { article },
  }));
}

paramsの名前が[...id]と一致するか、URLに使う値、下書き除外条件を見ます。1件だけ出ないなら、大文字小文字、全角記号、空白、階層を確認します。読み込みが失敗する場合はAstro Content Collectionsの型エラーを直す手順も参照できます。

trailing slashをそろえる

/about/about/の扱いが公開先とずれると、片方だけ404になることがあります。AstroのtrailingSlash'always''never''ignore'から選べます。公式ガイドも、配信先によって挙動が異なるため公開後に設定が必要な場合があると説明しています。

export default defineConfig({
  site: 'https://example.com',
  output: 'static',
  trailingSlash: 'always',
});

Astro公式は、事前生成したページの末尾スラッシュを実際にどう配信するかはホスティング側が扱い、Astroの設定どおりにならない場合があるとも明記しています。trailingSlashだけで直ったと判断せず、ナビゲーション、canonical、sitemap、_redirectsを統一し、公開URLで確認します。既存URLを変えるなら旧URLから転送し、canonical URLの書き方も確認してください。

リダイレクト設定を確認する

Cloudflare Pagesの静的リダイレクトは、通常public/_redirectsへ1行1ルールで書きます。

/old-page /new-page 301
/docs/* /guide/:splat 301

上から評価されるため、広いワイルドカードが個別ルールを隠すことがあります。転送先、ループ、dist/_redirectsへの出力を見ます。

Pages Functionsが同じパスに一致する場合、Cloudflare公式では_redirectsがそのリクエストへ適用されません。functionsを使うサイトでは、関数のルートが記事まで捕まえていないかも確認します。

SPA向け設定を混ぜない

全URLを/index.htmlへ200で書き換える設定は、JavaScriptルーターを使うSPA向けです。各記事をHTMLとして生成するサイトへ混ぜると、欠落を隠します。

Cloudflare Pagesはトップ階層に404.htmlがないとSPAとして扱い、見つからないパスをルートへ渡します。静的記事サイトでは404.htmlを生成し、存在しないURLが404になる状態を保ちます。

再読み込み対策だけを理由に/* /index.html 200を追加せず、先にHTMLと動的ルートを直してください。SPAを同居させる場合も、その領域だけへルールを限定します。

公開後に複数URLを検査する

修正後は固定ページ、動的記事、末尾スラッシュ違い、存在しないURLを検査します。

  • 正規URLを直接開き、再読み込みしても200になる
  • 非正規URLは正規URLへ転送され、転送先が200になる
  • 存在しないURLは独自404を表示し、HTTP状態も404になる
  • 対象HTMLが配信成果物に存在する

公開URLとpages.devで違うなら、カスタムドメイン側を調べます。独自キャッシュは古い応答の原因になり得ますが、生成物、配信内容、転送規則を先に確かめます。

URLの増加後も同じ検査を続けるなら、Astroサイトのリンク切れチェックを自動化する手順も参考になります。

よくある質問

Cloudflareのキャッシュ削除を最初に試すべきですか

先にdist内のHTML、Pagesの配信先、HTTP状態を確認します。Cloudflare公式は独自キャッシュが古い応答の原因になり得ると説明していますが、生成されていないHTMLはキャッシュ削除では戻りません。

サイト内リンクでは開くのに、再読み込みだけ404になるのはなぜですか

クライアント側の画面遷移では既に読み込んだJavaScriptが表示を切り替えられても、再読み込みではCloudflareへそのURLのファイルを直接要求します。静的サイトなら、そのURLに対応するHTMLが配信成果物に必要です。

/* /index.html 200を追加すれば直りますか

SPAでは選択肢になりますが、記事ごとのHTMLを生成するAstroサイトでは、生成漏れを隠す可能性があります。先にgetStaticPaths()distを直し、SPA領域がある場合だけ対象パスを限定します。

trailingSlash: 'always'にすればCloudflareでも必ず統一されますか

必ずとは限りません。Astro公式では、事前生成したページの末尾スラッシュはホスティング側の扱いに左右されるとされています。リンクとcanonicalをそろえたうえで、/page/page/の両方を公開環境で確認します。

_redirectsを書いたのに転送されないのはなぜですか

ファイルが最終出力へコピーされているか、上位ルールに隠れていないか、対象URLをPages Functionsが処理していないかを確認します。Cloudflare公式では、Functionsが処理するリクエストに_redirectsは適用されません。

まとめ

確認順は、URLを再現する、distを見る、getStaticPaths()を見る、末尾スラッシュを統一する、Cloudflareの規則を見る、公開URL群を再検査するです。この順ならAstroの生成漏れを設定で隠さず、再発時も同じ手順を使えます。

一次情報の確認メモ

続き(結論と実データ)はnoteに置いています

ここでは手順のところまで書きました。実際に出た数字、うまくいかなかった条件、そのまま使える設定ファイルは、 note の記事にまとめてあります。

noteで続きを読む Xをフォローする