2023年初頭、あるクライアントから連絡がありました。WordPressで約14,000件の記事を運営するメディアパブリッシャーで、6年間にわたり4人の開発者によって組み立てられたテーマを使っており、Core Web Vitalsのスコアは本当に恥ずかしいものでした。LCPはモバイルで7.2秒を記録していました。WP Rocketを試しました。CDNも試しました。プラグインの半分を削除したほどです。それでも遅い。問題はWordPress自体ではありませんでした。すべてのページレンダリングがPHP、膨張したテーマ、そして2018年から見直されていないデータベースクエリチェーンを通じていたことです。
重要なポイント:Headless WordPressとAstroの組み合わせはコンテンツサイトの最適解です。編集者向けにはwp-admin、訪問者向けには高速な静的フロントエンド、そしてWPGraphQLが両者を橋渡しします。
その時点で、フロントエンドとしてAstroを使用したヘッドレスセットアップに本気で取り組みました。流行だからではなく、数千件の記事とヘビーな編集コンテンツを扱うサイトにとって、それが唯一意味のあるアーキテクチャだったからです。
正確に設定した方法はこちらです。トレードオフ、実際の設定、私を困らせた部分です。
---
Astro が Next.js ではなく選ばれた理由
この質問はよくもらいます。React中心のチームがすでにいるか、複雑なクライアント側のインタラクティビティが必要なら、Next.jsは明らかな選択肢です。ただ、コンテンツが多いサイトなら?Astroの方が勝ります。そこまで迷う必要もありません。
AstroはデフォルトではゼロJavaScriptでシップします。ブログ、ニュースサイト、ドキュメンテーションポータルの場合、それが正しいデフォルトです。JavaScriptが必要な場所でオプトインするのであって、ほとんど必要のない200kbのReactバンドルからオプトアウトするのではありません。Astroドキュメントの部分的なハイドレーションについて、彼らはそれをIslands architectureと呼んでいますが、1文で説明するより上手に説明しています。短いバージョンはこうです。インタラクティブな部分だけがJSを取得します。記事本文、ヘッダー、サイドバー?静的HTML です。
2022年後半にNext.jsとWordPressで法律コンテンツサイトを構築しました。十分に速いのですが、クライアントは「今は速くなっているはずなのに、モバイルでLighthouseスコアが74なのはなぜか」と何度も聞きました。ハイドレーションのオーバーヘッド。Astroなら、同じタイプのサイトは今、定期的に95~98に達します。自慢ではなく、それはアーキテクチャが無料で与えてくれるものです。
Astroが得意でないこと
正直なところ。サイトがリアルタイムのパーソナライゼーション、重いショッピングカート、または多くのコンポーネント間でクライアント側の状態に本当に依存するものが必要なら、Astroは不便に感じられ始めます。Reactアプリではありません。Islands パターンは強力ですが、SPAを構築するのとは異なるメンタルモデルです。2023年中盤にクライアント向けダッシュボードをAstroプロジェクトに無理やり入れようとして、2週間以内にNext.jsに戻しました。何を作ろうとしているのかを知ってください。
---
WordPressをHeadless CMSとして設定する
WordPressは本当に良いheadlessバックエンドです。WP REST APIはコアに含まれていて、ドキュメントも充実していて、編集チームは何も新しく学ぶ必要がありません。その最後のポイントは、開発者が通常認める以上に重要です。
私が使う設定はこちらです:
- サブドメイン上にWordPressをインストールします。私はcms.yourdomain.comまたはapi.yourdomain.comを使用しています。基本認証の背後に保つか、最低でも直接的な公開トラフィックを制限してください。フロントエンドはyourdomain.comです。2つの別々のデプロイメント。
- [WPGraphQLプラグイン](https://www.wpgraphql.com/)をインストールします。コンテンツサイトではREST APIよりGraphQLを好みます。クエリをコンポーネントと共存させて、必要なフィールドだけをフェッチできるからです。オーバーフェッチングなし。REST APIは悪くありませんが、ポストタイプあたり15以上のカスタムフィールドがあると、GraphQLアプローチが明らかにクリーナーです。
- Advanced Custom Fields(ACF)とACF用WPGraphQL拡張をインストールします。この組み合わせがWordPressをヘッドレスコンテンツモデルとして本当に柔軟にします。ポストタイプごとに構造化データを定義し、GraphQLを通じて公開し、Astroがクリーンに消費します。
- コメント、絵文字、デフォルトのXML-RPCをまだ無効にしていなければ、無効にしてください。これらはオーバーヘッドと攻撃対象を増やすだけです。
- ビルドを始める前に、パーマリンクを適切に設定してください。Astroのルートが既に設定されている途中でパーマリンクを変更するのは、本当に面倒です。
人々を困らせる一つのこと:CORS。デフォルトでは、WordPressはAstro開発サーバー(localhost:4321で実行中)からのリクエストを許可しません。開発中は、テーマの functions.php またはちょっとしたユーティリティプラグインに以下を追加してください:
`` add_action('init', function() { header("Access-Control-Allow-Origin: *"); }); ``
本番環境では特定のオリジンに限定してください。当然のことながら。
---
Astroプロジェクト構造
複数プロジェクト全体で、これは一貫性のある自分のやり方です。ダース単位のヘッドレスビルドをしてきて、これが機能するものです:
`` src/ components/ layouts/ pages/ index.astro blog/ [slug].astro lib/ wpgraphql.ts ← すべての WP クエリロジックはここに格納 styles/ ``
lib/wpgraphql.tsファイルは、すべてのGraphQLフェッチを集約する場所です。ページファイル全体に散在するインラインフェッチコールなし。すべてのクエリは、名前が付けられた、エクスポートされたasync関数です。14,000件の記事をこれでデバッグすること、朝の2時に何かが壊れるとき、あなた自身に感謝するでしょう。
ビルド時に投稿をフェッチする
Astro の getStaticPaths はここで最も重要です。数千の投稿を持つブログの場合:
`` export async function getStaticPaths() { const posts = await getAllPostSlugs(); // calls WPGraphQL return posts.map(post => ({ params: { slug: post.slug }, })); } ``
getAllPostSlugsはafterカーソルを使用してWPGraphQLを通じてページングします。WordPressのGraphQLレイヤーはデフォルトリクエストあたり100件の記事を返すため、14,000件の記事では140件のリクエストをビルド時に作成しています。恐ろしく聞こえます。実際には、まともなサーバーでは、完全なビルドは約4~5分で実行されます。1日に数回リビルドするサイトにとって、完全に許容可能です。
---
画像処理で気が狂わないようにする
これが誰もあまり話さない部分だ。WordPress は CMS サブドメインを指す画像 URL を保存している。Astro が静的にビルドしても、それらの画像は cms.yourdomain.com に存在したままなので、訪問者のブラウザが WordPress サーバーから画像をフェッチすることになり、CDN をバイパスする可能性がある。
これを処理するいくつかの方法:
- 両方のドメインの前に Cloudflare を配置する。最もシンプルなオプションだ。yourdomain.com と cms.yourdomain.com の両方を Cloudflare 経由でプロキシし、/wp-content/uploads/* に積極的なキャッシング設定を施せば、ほぼ問題ない。
- メディアオフロードプラグインを使う。WP Offload Media が好みだ。アップロードを S3(または互換性のあるストレージ)に移動して、URL を自動的に書き換える。真剣なトラフィックが予想されるサイトではこれが私のアプローチだ。WordPress サーバーは画像配信を完全に止める。
- Astro の Image コンポーネント。ビルド時にコントロールできる画像(GraphQL で取得したアイキャッチ画像など)なら、リモート URL を Astro の <Image> コンポーネントに渡せば、最適化、リサイズ、ビルド出力からの配信を行う。素晴らしい動作だ。ただし記事本文の HTML に埋め込まれた画像には機能しない。別の処理が必要だ。
Seahawk は去年、旅行関連のコンテンツクライアントを抱えていた。約 8,000 ポスト、極めて画像多用型、1 記事あたり平均 12 画像。ヘッドレスセットアップでも WordPress サーバーは画像リクエストだけでハンマーのような負荷を受けていた。S3 + CloudFront に移行したら、オリジンの帯域幅が 94% 削減された。ホスティング料金に対して本当に革新的な変化だった。
---
インクリメンタルビルドと再構築の問題
スタティック生成を大規模で運用する際の実際の課題がこれだ:編集者が午後 3 時に投稿の訂正を公開して、フルリビルドが完了するまで 5 分待たなければいけない。ニュースルーム環境ではこれは受け入れ難い。
私が使ってきた方法がいくつかある:
オプション 1: Netlify または Vercel のオンデマンド ISR。Astro はアダプタでサーバーサイドレンダリングに対応している。ハイブリッドモードで Astro を実行でき、ほとんどのページは静的だがする特定のルートはオンデマンドでレンダリングされる。ニュースサイトなら、過去 30 日分のポストは静的にプリレンダリング(トラフィック大、速度が必要)して、古いアーカイブページはサーバーレンダリングに設定する。両者の良いところを得られる。
オプション 2: webhook トリガーの部分ビルド。WordPress はポスト保存時に webhook を発火させる(WP Webhooks プラグインで簡単)。その webhook が Netlify または Vercel のデプロイフックを叩く。ビルドが走って変更分だけをフェッチする。本当の意味での部分ビルドではなく、Astro は依然すべてをリビルドするが、ビルドを高速に保てば 4 分は実用的だ。
オプション 3: サイト全体に SSR を使う。Node アダプタで Astro を VPS にデプロイする(私は Hetzner を使う。安い、速い、信頼性がある)。すべてのページはリクエスト時にレンダリングされ、Nginx または Cloudflare レベルで積極的にキャッシュして、ポスト更新は即座に反映される。50,000 ポスト以上の適切なパブリッシング操作なら、これが私のやり方だ。
本音を言えば、ほとんどのサイトはオプション1または3の複雑性を必要としません。Webhook でトリガーされる4分間のリビルドはコンテンツサイトの90%に十分です。
---
パフォーマンス:実際に得られるもの
冒頭のパブリッシャープロジェクトの後、Astro 移行後に何が起きたかここに示す:
- モバイル上の LCP は7.2秒から1.1秒に低下しました(WebPageTest でロンドンノードからテストした結果)
- Total Blocking Time は約800ミリ秒からゼロに低下しました(デフォルトではゼロJS のことを思い出してください)
- Google Search Console の Core Web Vitals レポートはデプロイメントから6週間以内に「良好」URL が3%から91%に向上しました
- ホスティングコストは削減されました。WordPress サーバーはページを提供しなくなり、API レスポンスのみになったためです
これは魔法ではありません。PHP レンダリングをクリティカルパスから除去し、すべての読者に400kb のテーマ JavaScript バンドルを配信するのをやめることで起こるだけです。
---
つまずきやすいポイント
本当のところ、実際のプロジェクトでデバッグしなければならなかった事柄:
- 下書き投稿のプレビュー。ヘッドレス設定では本当に面倒です。WordPressのネイティブプレビューはフロントエンドレンダリングに依存しています。WordPressのプレビューnonce を受け取ってWPGraphQL経由で下書きを取得するカスタムプレビューエンドポイントをAstroで構築する必要があります。難しくはありませんが、きちんとやるのに1日かかります。
- リダイレクト。古いサイトに.htaccessに数百個のリダイレクトがあった場合、それらはいまWordPressサーバーに存在しています。Astroの設定で複製するか、WordPressにアクセスしたままで特定パスをプロキシするか、どちらかが必要です。両方やったことがあります。Astroで複製するほうが長期的にはきれいです。
- 検索。WordPressの組み込み検索はヘッドレス設定では役に立ちません。Algoliaと「WP Search with Algolia」プラグインを使っています。WPで投稿をインデックス化して、Astroの Island コンポーネントからAlgoliaをクエリします。よく機能します。
- メニューとナビゲーション。WordPress メニューは WPGraphQL を通じて公開するのが妙に厄介だ。wpgraphql-acf ルートがより簡潔に終わることが多く、nav を ACF repeater としてモデル化して終わりにすればいい。
---
FAQ
WPGraphQLが必要ですか、それともREST APIだけでいいですか?
REST APIを使うのは全く問題ありません。WordPress コアに組み込まれていて、追加プラグインは不要です。標準的なポストタイプと最小限のカスタムフィールドの簡単なサイトであれば問題ありません。GraphQL の出番は、多くのカスタムフィールドを持つ複雑なコンテンツモデルがある場合です。必要なフィールドだけを1回のリクエストで取得でき、_embed パラメータやネストされた REST 呼び出しと格闘する必要がないのは、書くクエリごとに時間を節約できます。どちらを選ぶかはあなた次第です。個人的には、ある程度の複雑さを超えると GraphQL の方がすっきりしていると感じます。
メンバー限定コンテンツのWordPress認証はどのように処理しますか?
JWT 認証が標準的なアプローチです。JWT Authentication for WP REST API プラグインをインストールしてログイン時にトークンを発行し、GraphQL リクエストヘッダーで渡します。Astro 側では SSR ルート(静的ではなく)で処理するので、ユーザー固有のコンテンツはリクエストごとにサーバー側で取得されます。これを静的にしようとしてはいけません。そこは地獄への道です。
小規模ブログにとっては過度ではありませんか?
おそらくそうです。500件以下のポストと1人のエディターであれば、ヘッドレスセットアップを維持するオーバーヘッドは見合いません。優れたWordPressテーマを使い、画像を最適化して、それで済ませてください。このアーキテクチャが報われるのは、ボリューム、編集の複雑さ、またはパフォーマンスが収益に実質的な影響を与えるレベルのトラフィックがある場合です。
本番環境のホスティング構成はどのような感じですか?
WordPress(CMS のみ)は小規模な VPS またはマネージド WordPress ホスト上に置きます。私は Kinsta または Cloudways を使っています。Astro フロントエンドは Vercel、Netlify、またはプロジェクトに応じて Nginx を備えた Hetzner VPS に配置します。すべての前に Cloudflare を配置します。中規模なコンテンツサイトの月額コストは通常 £60~£120 で、負荷に耐えられていなかったオールインワン WordPress ホストでクライアントが支払っていた料金よりも少ないことがほとんどです。
---
正直な要約は以下の通りです。ヘッドレスWordPressとAstroは、コンテンツサイトにしばらくの間起きた最良の事柄の1つです。新しいからではなく、ツールがようやくそのアイデアに追いついたからです。WPGraphQLは安定しており、Astroのビルドシステムは高速で、パフォーマンスゲインは実数で測定可能です。
画像戦略と再ビルドアプローチ特に、アーキテクチャを早い段階で正しく組み立てれば、後で消火活動に費やす時間をはるかに少なくできます。それだけです。
