つれづれなる Agent OPS
Cloudflare

Cloudflare PagesでNext.jsの静的サイトを無料公開してみる

Next.jsで作った静的サイト「戦略の系譜」をCloudflare Pagesへデプロイし、ローカル確認、ビルド、wrangler設定、Productionデプロイ、独自ドメイン公開までを確認した実験ログ。

はじめに

個人開発を始めると、最初に地味に詰まるのが公開環境です。

アプリ本体を作る前に、LPを置きたい。技術ブログを公開したい。小さなメディアサイトを試したい。そう思っても、いざ公開しようとすると、ホスティング、独自ドメイン、SSL、ビルド設定、環境変数、デプロイ方法など、細かい判断が一気に出てきます。

VercelやNetlifyを使えばすぐに公開できます。ただ、Cloudflare Pagesもかなり強い選択肢です。静的サイトであれば、無料枠で公開しやすく、独自ドメインも扱いやすく、CloudflareのCDN上で配信できます。

今回は、実際に自分で公開したサイトを題材にして、Cloudflare Pagesで静的サイトを公開する流れを確認します。

対象にするのは、次のサイトです。

https://bukei-wisdom.com/ 戦略の系譜 歴史的英雄たちの戦略決断を古典の教えで分析し、現代への応用を探る知恵の宝庫 https://bukei-wisdom.com/

「戦略の系譜」という、東洋古典や兵法書を扱う静的サイトです。実装はNext.jsで、Cloudflare Pagesへデプロイしています。

今回公開したもの

今回公開したのは、Next.jsで作った静的サイトです。

Browser

Cloudflare Pages

Next.js static export

対象プロジェクトは、手元では「戦略の系譜」プロジェクトの app 配下にあります。

bukei_shichisyo/

アプリ本体は app 配下です。

bukei_shichisyo/
  app/
    package.json
    wrangler.toml
    out/

今回確認したことは、次の6つです。

  • ローカルでNext.jsサイトを表示できるか
  • Next.jsの静的ビルドが通るか
  • sitemapが生成されるか
  • Cloudflare Pages向けの出力先が out になっているか
  • Cloudflare PagesのProductionデプロイが成功しているか
  • 独自ドメイン bukei-wisdom.com で表示できるか

最初から結論を書くと、Cloudflare PagesでNext.jsの静的サイトを公開する流れは成立しました。

ただし、Cloudflare Dashboard上でBuild commandやRoot directoryが常に分かりやすく見えるわけではありませんでした。今回はWrangler CLIと wrangler.toml の設定を根拠に、デプロイ構成を確認しています。

なぜCloudflare Pagesを使うのか

静的サイトの公開先としては、Vercel、Netlify、GitHub Pagesなど、いくつか選択肢があります。

その中でCloudflare Pagesを使う理由は、Cloudflareの他サービスへ広げやすいからです。

最初は静的サイトだけで十分です。しかし、個人開発を続けていると、問い合わせフォーム、画像配信、API、認証、Bot対策、AI機能などを後から足したくなります。

Cloudflare Pagesを入口にしておくと、Workers、R2、KV、D1、Turnstile、AI Gatewayなどに広げやすいです。最初から全部使う必要はありませんが、あとから拡張できる余地があるのは安心です。

今回の「戦略の系譜」も、まずは静的サイトとして公開するところに絞りました。DBや認証は扱わず、公開環境としてCloudflare Pagesが使えるかを確認します。

ローカルで確認する

まず、手元でNext.jsサイトを表示します。

cd bukei_shichisyo/app
npm install
npm run dev

ローカルでは localhost:3000 で表示しました。

ローカルで表示した戦略の系譜

ここで確認したのは、サイトのデザインそのものではありません。Cloudflare Pagesへ出す前に、少なくともローカルでトップページが表示でき、主要なナビゲーションやカードが崩れていないことを確認しました。

公開環境の問題を調べる前に、ローカルで成立している状態を残しておくと、後で切り分けがしやすくなります。

ビルドする

次に、本番向けにビルドします。

npm run build

このプロジェクトでは、build 後に next-sitemap が走るようになっています。

package.json では、次のようなscriptになっています。

{
  "scripts": {
    "build": "next build",
    "postbuild": "next-sitemap"
  }
}

実際にビルドすると、next-sitemap の生成完了まで確認できました。

Next.jsビルドとsitemap生成の成功ログ

スクリーンショットでは、https://bukei-wisdom.com/sitemap.xml が生成対象として表示されています。

ここは地味ですが重要です。静的サイトを公開するだけなら、HTMLが表示されれば最低限は成立します。しかし、検索流入を考えるなら、sitemapまで生成されているかは確認しておきたいところです。

Cloudflare Pages向けの設定

Cloudflare Pages向けの設定は、app/wrangler.toml にあります。

name = "bukei-wisdom"
compatibility_date = "2024-01-15"
pages_build_output_dir = "out"
compatibility_flags = ["nodejs_compat"]

[env.production]
name = "bukei-wisdom"
compatibility_flags = ["nodejs_compat"]

[env.preview]
name = "bukei-wisdom-preview"
compatibility_flags = ["nodejs_compat"]

実際の設定画面は次の通りです。

Cloudflare Pages用のwrangler設定

ここで特に見るべきなのは、次の2つです。

name = "bukei-wisdom"
pages_build_output_dir = "out"

name はCloudflare Pagesのプロジェクト名です。pages_build_output_dir は、Cloudflare Pagesへデプロイする静的ファイルの出力先です。

今回のプロジェクトでは out を使っています。Astroであれば dist がよく出ますが、Next.jsの静的出力では構成によって out を使います。ここを間違えると、ビルドは通っているのにCloudflare Pages側で配信対象が見つからない、という状態になります。

デプロイしてみる

Cloudflare Pages側には、bukei-wisdom というプロジェクトとして作成されています。

Cloudflare Pagesのbukei-wisdom設定画面

今回の運用では、Cloudflare Dashboard上のBuild commandやRoot directoryの詳細値は確認できませんでした。Git連携のビルド設定画面というより、Wrangler CLI中心のPagesデプロイ運用になっているためです。

そのため、記事ではDashboardのBuild settingsではなく、次の2つを根拠にします。

  • wrangler.tomlpages_build_output_dir = "out"
  • package.json のCloudflare Pages向けscript

package.json には、Cloudflare Pages向けに次のscriptがあります。

{
  "scripts": {
    "pages:build": "npx @cloudflare/next-on-pages",
    "pages:deploy": "npm run pages:build && wrangler pages deploy",
    "deploy:production": "npm run build && npm run pages:build && wrangler pages deploy"
  }
}

デプロイは、基本的には次の流れです。

npm run build
npm run pages:build
wrangler pages deploy

または、scriptにまとめたコマンドを使います。

npm run deploy:production

Cloudflare PagesのProduction deploymentは成功しており、bukei-wisdom.combukei-wisdom.pages.dev が紐づいています。

Cloudflare PagesのProductionデプロイ成功画面

この画面では、Production環境、mainブランチ、デプロイ成功status、公開ドメインを確認できます。

独自ドメインで表示する

最後に、独自ドメインで表示できるかを確認します。

今回の本番URLは次の通りです。

https://bukei-wisdom.com/

実際にアクセスすると、Cloudflare Pages経由で「戦略の系譜」のトップページが表示されました。

bukei-wisdom.comで公開された戦略の系譜

PagesのProduction deployment画面でも、次の2つのドメインが確認できます。

bukei-wisdom.com
bukei-wisdom.pages.dev

Cloudflare Pagesでは、pages.dev のURLだけでも公開できます。しかし、検索やSNS共有、読者への見え方を考えると、独自ドメインを設定した方がサイトとして扱いやすくなります。

今回も、最終的には bukei-wisdom.com を主URLとして使う前提にしています。

実際に詰まりやすいところ

実際に確認して、Cloudflare Pagesで静的サイトを出すときに注意すべき点は3つありました。

1つ目は、出力ディレクトリです。

Astroなら dist、Next.jsの静的出力なら out のように、フレームワークや構成によって配信対象のディレクトリが変わります。今回の設定では、wrangler.tomlpages_build_output_dir = "out" が重要でした。

2つ目は、Cloudflare Dashboardで見える情報と、実際のデプロイ運用が一致しないことです。

Git連携のBuild settingsを使っている場合は、Build commandやRoot directoryがDashboardで見やすいです。一方で、Wrangler CLI中心でデプロイしている場合は、Dashboardだけを見てもすべての設定が分かるとは限りません。今回は、wrangler.tomlpackage.json のscriptを見て、デプロイ構成を確認しました。

3つ目は、sitemapです。

サイトが表示されるだけなら、sitemapは必須ではありません。しかし、検索流入を期待するなら、sitemap.xml が生成されているかを確認した方がよいです。今回のビルドログでは、next-sitemap によって https://bukei-wisdom.com/sitemap.xml が生成対象になっていることを確認できました。

この記事で分かったこと

Cloudflare Pagesは、Next.jsの静的サイトを公開する先として十分使えます。

今回の実例では、ローカル表示、Next.jsビルド、sitemap生成、Wrangler設定、Productionデプロイ、独自ドメイン表示まで確認できました。

特に、wrangler.tomlpages_build_output_dir = "out" を明示しておくと、Cloudflare Pagesへ何を配信するのかが分かりやすくなります。Dashboardだけで設定を追おうとすると見えない部分もあるため、リポジトリ内に設定を残しておくことは重要です。

個人開発では、サイトを作ることよりも、公開して継続的に直せる状態を作ることが大事です。

Cloudflare Pagesで一度公開まで通しておくと、その後にWorkers、R2、D1、Turnstile、AI Gatewayなどへ広げる足場になります。今回の「戦略の系譜」は静的サイトとして公開しましたが、将来的にフォーム、分析、AI機能を足す場合にも、Cloudflare上に置いてあることは拡張しやすさにつながります。

ぼやきとしては、公開記事に「あとでスクショを撮る」と書いたまま出してしまうのはよくないです。検証記事は、やはり動かした証跡まで揃えてから出した方が強いです。

DUO

Author

DUOps

LLMOps、Agent、MCP、Langfuse、Cloudflare 周辺の実装と運用を、個人で試しながら記録しています。

Xを見る

Related