実装ノウハウ 2026.06.26

WordPressはそのまま。表示だけ静的化する「ヘッドレスWP」の作り方

WordPressはそのまま。表示だけ静的化する「ヘッドレスWP」の作り方

この記事で分かること

  • ヘッドレスWP の仕組みと、なぜ「速い・SEO/AEO に強い」のか
  • Astro + WPGraphQL + ACF + Cloudflare Pages の構成と更新フロー
  • 実際にこのサイトを構築したときのハマりどころ

WordPress を捨てない理由

「フロントを速くしたい」という話をすると、「じゃあ WordPress をやめましょう」という提案になりがちです。でも、それには問題があります。

WordPress には、長年かけて蓄積されたコンテンツと、担当者が使い慣れた管理画面があります。移行コストは見積もりより必ずかさみます。そして何より、フロントが遅い原因は WordPress そのものではなく、「テーマが全部のページで PHP を動かして HTML を生成している」ことにあります。

ヘッドレス構成では、WordPress はコンテンツの保管場所(CMS)として残します。フロントの HTML は、別のツールがビルド時に一度だけ生成して、CDN に置きます。WordPress の表示エンジンを捨てて、中身だけ使う——これがヘッドレスの考え方です。


このサイトの構成

このサイト(teraone.site)は、以下の構成で動いています。

WordPress(レンタルサーバー)
  ↓ WPGraphQL で API 提供
Astro(ビルドツール)
  ↓ ビルド時に GraphQL でコンテンツ取得 → 静的 HTML 生成
Cloudflare Pages(CDN)
  → ブラウザへ配信

構成要素の役割:

ツール 役割
WordPress + WPGraphQL コンテンツの保管・GraphQL API の提供
ACF(Advanced Custom Fields) カスタム投稿タイプの詳細フィールド管理
Astro ビルド時にコンテンツ取得 → 静的 HTML を生成
Cloudflare Pages 静的ファイルを CDN で配信

更新フローは一本道

この構成で、更新フローはシンプルになります。

  1. WordPress の管理画面で記事を書いて「公開」を押す
  2. WordPress が Deploy Hook(URL)に通知を送る
  3. Cloudflare Pages がビルドを自動開始する
  4. Astro が WordPress から最新コンテンツを取得して静的 HTML を生成する
  5. 1〜2 分後、サイトに新しいコンテンツが反映される

担当者が触るのは WordPress の管理画面だけです。「公開」ボタンを押すとサイトが更新される——これだけ。フロントの仕組みを知らなくても使えます。


なぜ「速い」のか

通常の WordPress テーマは、ページが表示されるたびに PHP が動いて HTML を作ります。データベースへのアクセスが発生し、プラグインが動き、その結果を返します。

ヘッドレス構成では、HTML はビルド時に一度だけ作られて CDN に置かれます。訪問者のリクエストに対して CDN がキャッシュされた HTML を返すだけなので、PHP もデータベースも動きません。これが速い理由です。

このサイトで実測したパフォーマンス(Lighthouse スコア・執筆時点):

指標 スコア
パフォーマンス 98〜100
SEO 100
アクセシビリティ 100(全ページ)

なぜ「AI にも読まれやすい」のか

最近、「AI に読まれるサイト」という話を聞くことが増えました。ChatGPT や Perplexity などの AI アシスタントは、ウェブのページを巡回して情報を集めます。

ここで問題になるのが、主要な AI クローラの多くは JavaScript を実行しないという点です。React や Vue でクライアント側に描画される内容は、AI クローラには見えないことがあります。

Astro + ヘッドレスWP の構成では、コンテンツはビルド時に静的 HTML として出力されます。JavaScript の実行を必要とせず、HTML を読むだけでコンテンツが取れます。これが「AI にも読まれやすい」理由です。


実装のポイント

GraphQL でコンテンツを取得する

Astro では、ビルド時にデータを取得できます。WordPress に WPGraphQL プラグインを入れると、記事や固定ページを GraphQL で取得できるようになります。

// src/lib/wp.ts(抜粋・概念コード)
const ENDPOINT = import.meta.env.WP_GRAPHQL_ENDPOINT;

export async function getPostsList() {
  const res = await fetch(ENDPOINT, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      query: `{
        posts(first: 10) {
          nodes {
            slug
            title
            date
            excerpt
            categories { nodes { name } }
          }
        }
      }`,
    }),
  });
  const { data } = await res.json();
  return data.posts.nodes;
}

カスタム投稿タイプの詳細フィールドは ACF(Advanced Custom Fields)で管理し、wpgraphql-acf プラグインで GraphQL に公開します。

フォールバックで「絶対に空にならない」設計にする

WordPress への接続が一時的にできない場合に備えて、ダミーデータへのフォールバックを wp.ts に集約しています。営業装置として常にコンテンツを表示させるための設計です。

// wp.ts — フォールバック付きの例(概念コード)
export async function getWorksList() {
  try {
    const works = await fetchFromWP(); // WordPress から取得
    if (works.length > 0) return works;
  } catch {
    // WP 到達不可
  }
  return dummyWorks; // ダミーデータで常時表示
}

カスタム投稿タイプの GraphQL 公開には明示指定が必要

カスタム投稿タイプを wpgraphql-acf で GraphQL に公開するとき、2 つの設定が必要です。① CPT 登録時に show_in_graphql と型名を宣言する、② ACF フィールドグループの配列に graphql_types明示する——この両方が揃わないとフィールドが GraphQL に出てきません。

// CPT登録(mu-plugin・概念コード)
register_post_type('works', [
  // ...
  'show_in_graphql'     => true,
  'graphql_single_name' => 'Work',   // → GraphQL型名 "Work"
  'graphql_plural_name' => 'allWorks',
]);

// ACFフィールドグループをWork型に明示紐付け(概念コード)
acf_add_local_field_group([
  'key'    => 'group_works_fields',
  'fields' => [ /* ... show_in_graphql:1 を各フィールドに */ ],
  'location' => [[[ 'param' => 'post_type', 'operator' => '==', 'value' => 'works' ]]],
  'show_in_graphql'    => 1,
  'graphql_field_name' => 'worksFields',
  'graphql_types'      => ['Work'],   // ← CPTはlocation自動マッピングが効かない。これが無いとフィールドが出ない
]);

CPT(カスタム投稿タイプ)は location の自動マッピングが効かないため、graphql_types への明示指定が必須です。フィールドが空で返ってくるときは、まずここを疑ってください。


ドッグフーディング

この記事は、このサイト(teraone.site)の WordPress で書かれていて、ビルド時に Astro が GraphQL で取得して静的 HTML にしています。

つまり、この記事の配信自体が、記事に書いた仕組みの実証になっています。


まとめ

  • ヘッドレスWP は「WordPress はそのまま・表示だけ静的化」する構成
  • 更新フロー: WP で公開 → Deploy Hook → 自動ビルド → CDN 配信(1〜2 分)
  • 速い理由: 訪問時に PHP・DB が動かない。CDN からキャッシュが返るだけ
  • AI に読まれやすい理由: 静的 HTML で出力されるので、JS 非実行のクローラにも中身が届く
  • 実装のポイント: CPT + ACF の GraphQL 公開は型への明示紐付けが必要

ヘッドレスWP でのサイト構築・リプレイスについて、ご相談はお問い合わせから。→ お問い合わせ

ホームページの「困った」、聞かせてください

お見積もりは無料です。内容が固まっていなくても大丈夫。