ひとことで言うと

Workers & Pages → Create application → 画面下部「Looking to deploy Pages? Get started here」
→ GitHub連携 → Framework preset を「Astro」に設定 → Save and Deploy

「Create application」を押すとWorkers画面になるが、画面下部の小さいリンクがPages入口。Framework presetを「Astro」にするだけでNode.jsバージョン問題も回避できる。


やりたかったこと

Astroで作ったブログをCloudflare Pagesで公開しようとした。VercelからCloudflareに移行する目的だったが、Cloudflare PagesのUIがVercelと全然違って、最初どこから設定を始めればいいかわからなかった。

MediumでAstro+Cloudflareのデプロイ記事を見つけて読んでいたのだが、2年前の記事だった。スクリーンショットのUIが現在のCloudflareと全然違って「Pages」という独立したメニューが左サイドバーにあるように見えていた。今は「Workers & Pages」という項目にまとまっていて、記事の通りに操作しても「その画面がない」という状態になった。記事の日付を確認せずに参考にしたのが最初のミスだった。

「Create application」を押したらWorkers用の画面が出てきて、Pagesの設定入口がどこにあるかわからなくなった。Vercelなら「New Project」→GitHubリポジトリを選ぶだけで繋がるのに、Cloudflareは全然違う流れになっていた。

最終的に初回デプロイ完了まで3時間かかった。2回目以降は5分でできるようになった。3時間のトラブルは大きく3段階に分かれていた。「UI上でPagesの設定に入れない」「ビルドコマンドの設定ミス」「環境依存のビルドエラー」の3つだった。最初にこの3段階を知っていれば1時間以下で終わっていたと思う。

VercelのFreeプランはTeamメンバー数や帯域に制限があるが、Cloudflare PagesのFreeプランは月500回のビルドと月500GBの転送量が上限で、個人ブログの規模ではまず引っかからない。コスト面での移行メリットはあった。


環境

  • Windows 11
  • Node.js 20.11.0
  • npm 10.2.4
  • Astro 5.2.3
  • GitHub(リポジトリ作成済み)
  • Cloudflare Pages(Freeプラン)

試したこと・うまくいかなかったこと

「Create application」でWorkers画面が出た → Pages入口が見つからない

Cloudflareの「Workers & Pages」→「Create application」を押したら「Create a Worker」という画面になった。「Connect to Git」のようなボタンがなく、PagesへのGitHub接続がどこにあるか全くわからなかった。左サイドバーに「Pages」という独立したメニューはない。「Workers & Pages」が両方を兼ねているとわかるまで10分以上右往左往した。

「Create application」を押した後の画面の下の方に「Looking to deploy Pages? Get started here」という小さいリンクがあった。上部だけ見ていると気づかない。このリンクを見つけてから先に進めた。

Framework presetを手動入力した → Node.jsバージョン不一致でビルド失敗

ビルドコマンドを「npm run build」、出力ディレクトリを「dist」と手動で入力した。ビルドは失敗した。

error TS2339: Property 'xxx' does not exist on type 'ImportMeta'

ローカルのNode.js 20でコンパイルできるコードが、CloudflareのデフォルトNode.js 18環境でTypeScriptエラーになっていた。Framework presetで「Astro」を選べばNode.jsの推奨バージョンも適用されるのに、手動入力したせいで環境変数の設定漏れが起きた。この時点で2回ビルドを無駄にした。

devDependencies に入れたパッケージが本番ビルドでエラー

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'sharp'

sharpdevDependencies に入れていたのが原因。Cloudflareの本番ビルドは dependencies のみをインストールする。ローカルでは npm install で全部入っているから気づかなかった。

@astrojs/sitemap プラグインで site オプション未設定のエラーも出た。

[@astrojs/sitemap] No `site` option is set in your Astro config.

ローカルのdevモードではスキップされてもCloudflareのproductionビルドでは必須になる設定がいくつかあった。ローカルテストだけでは発見できないバグがこの段階で2件出た。

さらに @astrojs/mdx を使っていてこのエラーも出た。

Error: Cannot find module 'remark-gfm'

remark-gfm をoptionalDependenciesに入れていたのが原因で、これも dependencies に移すことで解消した。Cloudflare Pagesはどのdependency categoriesをインストールするか、Settings → Buildsの「Build command」で npm ci --include=dev のように明示的に変更することもできるが、パッケージを dependencies に移す方がシンプルだった。

ビルドは成功するが *.pages.dev のURLで「522 Connection Timed Out」

初回デプロイが「Success」になったので早速 *.pages.dev のURLにアクセスしたら、

522: Connection timed out

と表示された。「ビルドは成功したのになぜページが開かないのか」とかなり焦った。Cloudflareのエッジへの伝播に5分ほどかかっているだけで、5分待ってリロードしたら正常に開いた。

本番ビルドで初めて発覚するエラーを減らすには、ローカルでも本番と同じ環境を再現してビルドするのが有効だった。

# node_modulesを削除してdependenciesのみインストール
rm -rf node_modules
npm install --omit=dev
npm run build

これで本番環境と同じ条件でビルドが通るか事前確認できた。


解決策

1. Astroをインストールして動作確認

npm create astro@latest
cd プロジェクト名
npm run dev

http://localhost:4321 でAstroの画面が出れば成功。

2. GitHubにpush

git init
git add .
git commit -m "first commit"
git remote add origin https://github.com/ユーザー名/リポジトリ名.git
git branch -M main
git push -u origin main

pushする前に .gitignorenode_modules/.env が含まれているか確認する。node_modules をpushしてしまうとリポジトリサイズが膨大になってpushに数分かかるようになる。

cat .gitignore
# node_modules/、.env、dist/ が含まれていればOK

3. Cloudflare PagesにGitHubリポジトリを接続する

  1. 「Workers & Pages」→「Create application」を押す
  2. 画面下部の「Looking to deploy Pages? Get started here」をクリック(見落としやすい)
  3. 「Import an existing Git repository」→「Get started」
  4. GitHubアカウントを認証してリポジトリを選択
  5. ビルド設定でFramework presetを**「Astro」**に変更する

Framework presetでAstroを選ぶと以下が自動入力され、推奨Node.jsバージョンも適用される。

Build command: npm run build
Build output directory: dist
  1. 「Save and Deploy」でデプロイ開始

初回ビルドは2〜3分かかる。Deploymentsタブでビルドログをリアルタイムで確認できる。

4. ビルドが失敗した時の対処

よくあるエラーと対処法:

Error: Cannot find module 'sharp'

package.jsondependenciesdevDependencies ではない)に sharp があるか確認する。

error: No matching version found for node@xx.x.x

→ Settings → Environment variablesで NODE_VERSION=20 を追加する。

[@astrojs/sitemap] No `site` option is set in your Astro config.

astro.config.mjssite: 'https://yourdomain.com' を追加する。

ビルドログは「Download logs」でテキストとして保存してから Error: で検索すると原因が一発で見つかる。ブラウザのログビューアをスクロールしながら探すより圧倒的に速い。

Installing dependencies...   ← ここでエラーが出れば依存問題
Building Astro site...       ← ここでエラーが出ればビルド設定問題
  → rendering pages...       ← ここでエラーが出ればページ内容の問題

5. 環境変数の設定

Settings → Environment variablesで追加する。NODE_VERSION=20 は最初から設定しておくと安定する。

NODE_VERSION = 20

TypeScriptエラーがローカルでは出ないのにCloudflareで出る場合、ほぼ確実にNode.jsバージョン差異が原因。NODE_VERSION を揃えるだけで解消するエラーが多かった。

6. デプロイ完了後の確認

Deploymentsタブで「Success」になったら *.pages.dev のURLが発行される。デプロイ直後は「522 Connection Timed Out」が出ることがある。CloudflareのエッジへのDNS伝播中で、5分待ってからリロードすると正常に表示された。

7. プレビューデプロイの活用

main 以外のブランチへのpushに対しても自動でプレビューURLが発行される。

git checkout -b feature/add-new-section
# 変更を加えた後
git push origin feature/add-new-section

プレビューURLはDeploymentsタブの該当ビルドから確認できる。本番環境変数は引き継がれないので注意。

8. 以降のpushの流れ

一度設定が完了すれば、git push するだけで自動デプロイが走る。

git add src/pages/posts/new-post.md
git commit -m "add new post"
git push

pushから1〜2分でDeploymentsタブに新しいビルドが来て、2〜3分でデプロイ完了する。

9. 直前のデプロイに戻したい場合

DeploymentsタブのビルドエントリにあるRollback機能で以前のデプロイに戻せる。

  1. Deploymentsタブを開く
  2. 戻したいビルドの「…」→「Rollback to this deployment」
  3. 1〜2分で以前のビルドが本番に反映される

Rollbackはデプロイ先を変えるだけでGitのコミット履歴には影響しない。Rollback後に git push すれば最新コミットの内容で再びビルドが走る。

10. カスタムドメインの設定

デプロイが安定したらカスタムドメインを設定する。

  1. Cloudflareダッシュボードで対象プロジェクトを開く
  2. 「Custom domains」タブ → 「Set up a custom domain」
  3. 取得済みのドメイン名を入力
  4. DNSの設定指示に従ってCloudflareのNameserverを設定

ドメインをCloudflare自体で管理している場合は自動でDNSが設定される。別のレジストラで管理している場合はCNAMEレコードを手動で追加する。


ハマったポイント

  • 「Create application」を押すとWorkers用の画面になる。Pages用は画面下部の「Looking to deploy Pages? Get started here」という目立たないリンクから入る。上部だけ見ていると絶対に見つからない。Vercelとは全く違うUI設計で、最初にここで10分以上時間を取られた
  • Framework presetで「Astro」を選ばずに手動でビルドコマンドを入力すると、推奨Node.jsバージョンの環境変数が設定されない。ローカルはNode.js 20でもCloudflareのデフォルトが古くて、TypeScriptのエラーがCloudflareのビルドでだけ出る状態になった。最初からFramework presetを「Astro」に設定するだけで避けられる失敗だった
  • devDependencies に入れたパッケージはCloudflareの本番ビルドでインストールされない。ローカルでは npm install で全部入っているから気づかないが、Cloudflare側では dependencies のみが対象。Astroのintegrationなど実行時に必要なものは dependencies に入れる
  • ローカルのdevモードでは正常に動いても、Cloudflareのproductionビルドで初めて発覚するエラーがある。@astrojs/sitemapsite オプション未設定エラーがその一つで、devモードではスキップされる。全てのプラグインのドキュメントにある「Required for production」の項目は最初から確認しておくべきだった
  • 2年前のUI記事のスクリーンショットが現在のCloudflareと全然違っていた。「Workers」と「Pages」が統合されて「Workers & Pages」になったのが2023年頃で、古い記事では「Pages」が独立メニューに見えていた。GitHubやCloudflare関連のチュートリアルは記事の日付を必ず確認してから参考にする
  • 初回デプロイ「Success」直後の「522 Connection Timed Out」でビルドが失敗したと思い込んでしまった。Cloudflareのエッジへのプロパゲーションが完了するまで5分程度かかる。焦って再デプロイやCloudflare設定を触り始めてしまったが、待つだけでよかった

よくある質問

Q: VercelからCloudflare Pagesに移行するメリットはありますか? Cloudflare PagesのFreeプランは月500回のビルドと月500GBの転送量が上限で、個人ブログの規模ではまず引っかからない。VercelのFreeプランはTeamメンバー数や帯域制限がある。ただしVercelはAI機能やEdge Functionsの統合が手厚いので、静的なブログであればCloudflare Pagesの方がコスト面で優位。

Q: デプロイ後に「522 Connection Timed Out」が出ます。 デプロイ直後はCloudflareのエッジへのDNS伝播中で数分間出ることがある。5分待ってからリロードすると直ることが多い。それでも続く場合はDNS設定に古いAレコードが残っていないか確認する。

Q: ローカルでビルドが通るのにCloudflareでビルドエラーになります。 最もよくある原因はNode.jsバージョンの違い。Settings → Environment variablesで NODE_VERSION=20 を追加する。devDependencies に入れたパッケージが本番ビルドでインストールされないことも原因になる。必要なパッケージは dependencies に入れる。

Q: mainブランチ以外のpushでもデプロイが走りますか? はい。Cloudflare PagesはすべてのブランチへのpushでプレビューURLを生成する。本番(Production branch)とは別のURLになる。不要なブランチのビルドを止めたい場合はSettings → Buildsで「Enable Preview deployments」をオフにできる。

Q: デプロイが失敗し続ける場合の最終手段は? 「Disconnect Git repository」で接続を切断してから「Connect to Git」で接続し直す。これで設定が初期化される。Framework presetもAstroを選び直して、環境変数も再設定する。接続し直しで解消したケースが何度かあった。


関連記事

ドメイン取得はこちら

Cloudflareと組み合わせるドメインの取得に。

より詳しく学びたい方へ

この記事の内容をさらに深掘りした実践ガイドをZennで公開しています。

VPS・GitHub Actions・Cloudflare 実践構築ガイド