WordPressをやめてCloudflareに移行した|Astro×Workersでサーバー代0円、記事はMarkdownで書く
目次
このブログ「趣味と仕事の狭間」を、WordPressからCloudflareに移行しました。
はてなブログから始まり、WordPress(SANGO)で長く運用してきましたが、今回はWordPress自体をやめて、静的サイトとしてCloudflareで配信する形に変えています。
以前にもWordPressのサーバー引っ越しは何度かしていて、そのたびに地味に大変だったので、今回は「そもそもサーバーを持たない」方向に振り切りました。
なぜWordPressをやめたのか
理由はシンプルで、更新頻度に対して維持コストが見合わなくなったからです。
最近の更新は月1回くらい。それでもWordPressを動かしている以上、サーバー代はかかりますし、本体・テーマ・プラグインのアップデートも定期的に必要です。放置するとセキュリティ的にも不安が残ります。
一方で、このブログに必要な機能はそこまで多くありません。
- 記事とカテゴリの表示
- 商品リンク(Rinker)
- 人気記事ランキング
- お問い合わせフォーム
これくらいなら、データベースもPHPもいらない静的サイトで十分に実現できます。
EmDashも検討したけど、Astroの静的サイトにした
2026年4月にCloudflareが「WordPressの精神的後継」をうたうEmDashというCMSを出していて、最初はこれも候補にしていました。管理画面からWordPressのように記事を書けて、Cloudflare Workersで動くCMSです。
ただ、
- 無料プランだとプラグイン機能(Dynamic Workers)が使えない
- まだ出たばかりで、テーマやプラグインがほとんどない
- 月1回の更新なら、管理画面はなくても困らない
という理由で、今回は見送りました。代わりに選んだのが、EmDashの土台にもなっているAstroで静的サイトを作る方法です。あとからEmDashに乗り換えたくなっても、Astroなら移行しやすいはずです。
構成と費用
最終的な構成はこんな感じです。
| 役割 | 使ったもの | 費用 |
|---|---|---|
| サイト生成 | Astro(静的サイトジェネレーター) | 無料 |
| 配信 | Cloudflare Workers(静的アセット) | 無料 |
| 記事の管理・自動公開 | GitHub(非公開リポジトリ)+GitHub Actions | 無料 |
| サイト内検索 | Pagefind | 無料 |
| お問い合わせフォーム | Workers+Email Routing+Turnstile | 無料 |
| アクセス解析・人気記事 | Cloudflare Web Analytics | 無料 |
| ドメイン | takeiho.com | 年間のドメイン代のみ |
ポイントは、Cloudflare Workersの静的アセットへのリクエストは無料で無制限なことです。Workersの無料プランには「1日10万リクエスト」の上限がありますが、これはプログラム(Worker)が動いたときだけカウントされます。
このブログでWorkerが動くのは、お問い合わせの送信、旧URLのリダイレクト、404ページのときだけ。普通に記事が読まれるぶんには上限を気にする必要がありません。
移行の流れ
作業は大きく分けてこの5つです。
WordPressからデータを書き出す
管理画面の「ツール → エクスポート」で、記事・固定ページ・カテゴリなどを含んだXMLファイル(WXR形式)を書き出します。
記事をMarkdownに変換する
XMLを読み込んで、1記事ずつMarkdownファイルに変換します。画像もダウンロードして、記事と同じフォルダに保存します。
デザインを作る
Astroでトップページ、記事ページ、カテゴリページなどを作ります。今回はこの機会にデザインを一新しました。
Cloudflareに公開する
GitHubにpushすると、GitHub ActionsがビルドしてCloudflare Workersに公開するようにしました。
ドメインを切り替える
動作確認ができたら、takeiho.comの向き先を新しいサイトに切り替えます。
正直に書くと、変換スクリプトやデザインのコードの大部分はClaude Code(AIのコーディングツール)に書いてもらいました。自分は方針を決めたり、Cloudflareのダッシュボードでの設定をしたりが中心です。それでも、移行で気をつけるべきポイントは色々あったので、以下にまとめておきます。
記事の変換で大変だったところ
SANGOとRinkerの装飾
一番手間がかかったのは、テーマやプラグイン独自の装飾です。このブログでは、
- SANGOのボックス、吹き出し、タイムライン(手順)
- Rinkerの商品リンク(700か所以上)
- 関連記事カード
などを使っていましたが、これらはWordPressの外では当然動きません。そこで、Markdownで書ける独自の記法を用意して、変換時に置き換えています。
たとえばボックスはこう書きます。
:::point{title="結論"}
明るい部屋でも使える、今いちばんおすすめの1台です。
:::
Rinkerの商品リンクはこうです。
::product{asin="B0XXXXXXXX" title="商品名" keyword="検索キーワード"}
AmazonのアソシエイトIDや楽天のアフィリエイトIDは、表示するときに自動で付くようにしています。Rinkerの商品データはWordPressのエクスポートに含まれているので、過去の商品リンクもそのまま移行できました。
はてなブログ時代の記事
このブログは元々はてなブログで書いていたので、古い記事は書き方がバラバラでした。
- 段落が
<p>タグではなく改行だけで区切られている(クラシックエディタ時代の記事) - 画像がはてなフォトライフに置いてある
- 内部リンクが
/entry/2016/12/07/020555のような、はてなブログ形式のURL
改行の扱いはWordPress本体と同じ処理(wpautop)を通してから変換し、画像ははてなフォトライフからもダウンロード、古いURL形式のリンクは今の記事URLに書き換えています。
MacとLinuxで画像のファイル名が一致しない
これは完全に想定外でした。
手元のMacではビルドできたのに、GitHub Actions(Linux)でだけ「画像が見つからない」というエラーになりました。原因は日本語ファイル名の濁点です。
Macでスクリーンショットを撮ると、「ビ」が「ヒ+゛」のように分解された形(NFD)でファイル名に入ることがあります。Macはこの違いを区別しないので問題になりませんが、Linuxでは別のファイル名として扱われます。さらにGitがファイル名だけを結合した形(NFC)に直していたため、記事の中の画像パスとファイル名が食い違っていました。
URLは変えない
SEO的に一番大事なのは、今のURLを変えないことだと思います。
このブログの記事URLは/entry/記事のスラッグ/、カテゴリは/entry/category/親カテゴリ/子カテゴリ/という形だったので、Astro側でもまったく同じURLになるようにページを作っています。
それに加えて、
- はてなブログ時代のURL(
/entry/2016/12/07/020555など) - 途中でスラッグを変えた記事の古いURL
- WordPressのフィードURL(
/feed/)
は、新しいURLに301リダイレクトするようにしました。この処理はWorkerで行っていますが、該当するファイルが無いときだけWorkerが動く設定にしているので、普通のページ表示ではWorkerは動きません。
人気記事ランキング
静的サイトには「アクセス数を数える」仕組みがないので、人気記事は少し工夫しました。
- Cloudflare Web Analyticsでページビューを計測する
- 毎朝GitHub Actionsで、直近30日のページビューをAPIで取得する
- それをもとにランキングを作り直して、サイトを再公開する
移行直後でまだデータが少ないうちは、WordPressのプラグインに残っていた累計の閲覧数を使ってランキングを補っています。
お問い合わせフォーム
お問い合わせフォームは、WorkerとCloudflareのEmail Routingでメールを送っています。もともとinfo@takeiho.com宛てのメールはEmail RoutingでGmailに転送していたので、その仕組みをそのまま使えました。
スパム対策にはCloudflareのTurnstile(無料のCAPTCHAの代わり)を入れています。
ドメインの切り替えでハマったところ
Aレコードが残っていると割り当てられない
takeiho.comはすでにCloudflareのDNSで管理していたので、切り替えは「WordPressサーバー向けのAレコードを消して、Workerにドメインを割り当てる」だけです。
ただ、Aレコードを残したままだとWorkerにドメインを割り当てられません(エラーになります)。なので、
- 元に戻せるように、今のAレコードの値をメモしておく
- takeiho.comのAレコードを削除する
- すぐにWorkerにドメインを割り当てる
という順番でやりました。削除してから割り当てまでの数十秒〜数分だけ、サイトが見られない時間があります。
wwwのリダイレクトでドメインが二重になった
www.takeiho.comは、CloudflareのRedirect Ruleでtakeiho.comにリダイレクトしています。このとき、テンプレートの「Redirect from WWW to Root」をそのまま使ったら、
https://takeiho.comtakeiho.com/
という謎のURLに飛ばされるようになりました。
原因は、条件のhttps://www.*の*が「www.より後ろ全部(ドメイン名を含む)」にマッチしていたことです。条件と転送先を次のように直したら、正しく動きました。
| 項目 | 値 |
|---|---|
| Request URL | https://www.takeiho.com/* |
| Target URL | https://takeiho.com/${1} |
http → https
最後に、SSL/TLSの設定で「Always Use HTTPS」をオンにして、http://でアクセスされたときもhttps://に転送されるようにしました。サーバーを持たない構成になると、こういう細かい設定を自分で入れる必要があります。
今の記事の書き方
移行後の記事は、こんな感じで書いています。
npm run new -- スラッグ "タイトル"で記事のひな形を作る- VS CodeでMarkdownを書く。画像はVS Codeに貼り付けるだけで、記事と同じフォルダに保存される
npm run devでプレビューしながら書くgit pushすると、数分で公開される
画像は大きいまま置いておけば、公開時にWebP変換や縮小を自動でやってくれるので、事前に圧縮する手間もなくなりました。
まとめ
WordPressからCloudflare(Astro×Workers)への移行をまとめました。
- 更新頻度が低いブログなら、静的サイト+Cloudflareでサーバー代0円にできる
- 一番大変なのは、テーマやプラグイン独自の装飾の変換
- URLを変えず、古いURLはリダイレクトすればSEOの影響は抑えられる
- ドメイン切り替えは、DNSのAレコードとwwwのリダイレクトに注意
もう少し様子を見て、問題がなければWordPressのサーバーは解約する予定です。同じようにWordPressの維持が負担になっている方の参考になればうれしいです。