WordPressデータベースをバイパス: ゼロコンフィグCORSで静的JSONを取得する方法 のカバー画像

aritrhk

Next.jsやAstroのようなモダンなフロントエンドフレームワークでヘッドレスWordPressサイトを構築することに決めたとしましょう。素晴らしい開発者体験のように聞こえますが、2つの有名な障害にぶつかるまでです:

  1. CORS地獄:ローカルの開発サーバーをhttp://localhost:4321またはhttp://localhost:3000で立ち上げ、fetchリクエストを実行すると... ブラウザコンソールが赤いCORSポリシーエラーで溢れます。
  2. 遅いREST API:標準のWordPress REST APIやWPGraphQLはすべてのリクエストでWordPressコア全体を起動し、MySQLにクエリを実行します。応答時間は300msから1秒程度で、ビルドを遅くし、動的なサーバーサイドフェッチを遅延させます。

WordPressを静的JSONジェネレーターに変換し、データベースクエリなしでAPIペイロードを即座に提供し、管理パネルから直接CORSヘッダーを管理でき、サーバー設定が不要だったらどうでしょうか?

以下は、オープンソースのStatic JSON Export & CORS Whitelistプラグインを使用して1分以内にこれを実現する方法です。


検討された代替タイトル

  • Astro / Next.jsで1分でWordPress CORS問題を解決する方法
  • WordPressデータベースをバイパス: ゼロコンフィグCORSで静的JSONを取得する方法(採用)
  • ヘッドレスWordPressのクリーンな方法: 静的JSON + ゼロSDKプラグイン

仕組み:静的JSON vs 動的データベースクエリ

従来のヘッドレスセットアップでは、フロントエンドがヒットするたびにデータベースにクエリを実行します:

[従来のREST API]
フロントエンドフェッチ ──> WordPress起動 ──> MySQLクエリ実行 ──> JSONフォーマット ──> ペイロード返却 (200-500ms)

フルスクリーンモードに入る フルスクリーンモードを終了

静的JSONエクスポートアーキテクチャでは、データベースはバイパスされます:

[静的JSONエクスポート]
コンテンツ更新 ──> バックグラウンドで静的JSONファイル書き込み
フロントエンドフェッチ  ──> WordPress RESTエンドポイント  ──> JSONファイルを直接読み込み ──> ペイロード返却 (30-50ms)

フルスクリーンモードに入る フルスクリーンモードを終了

JSONは公開時にプリレンダリングされるため、フィード提供時のデータベースクエリ数はゼロとなり、トラフィックスパイク時のサーバー負荷を大幅に削減します。


1分のWordPressセットアップ

  1. 公式WordPressプラグインディレクトリからStatic JSON Export & CORS Whitelistを検索してインストールします。
  2. ダッシュボードのJSON Export CORS設定ページを開きます。
  3. CORS Allowed Originsリストに開発用URL(例:http://localhost:4321またはhttp://localhost:3000)を追加します。
  4. JSON Feeds Settingsで、postタイプの新しいフィードにpostsという名前を付け、Save Settingsをクリックします。

プラグインはすぐに投稿を静的JSONファイルにエクスポートします。2つのクリーンなエンドポイントが得られます:

  • Feed Index: https://your-wp.com/wp-json/sjec/v1/feed?name=posts
  • Single Post Details: https://your-wp.com/wp-json/sjec/v1/post?feed=posts&slug=hello-world

フロントエンドとの接続

AstroとNext.jsでこのクリーンでCORS対応の静的JSONフィードを利用する方法は非常にシンプルです。

例A: Astro(静的サイト生成)

Astroの静的ファーストアプローチは静的JSONフィードに最適です。

---
// src/pages/index.astro
interface Post {
  id: number;
  title: string;
  slug: string;
  excerpt: string;
  date: string;
}

// 静的JSONフィードを取得(WPでDBクエリは実行されません)
const response = await fetch('https://your-wordpress-site.com/wp-json/sjec/v1/feed?name=posts');
if (!response.ok) {
  throw new Error('Failed to fetch posts');
}
const posts: Post[] = await response.json();
---

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Fast Headless Astro Blog</title>
  </head>
  <body class="max-w-3xl mx-auto py-12 px-4 bg-slate-50 text-slate-800">
    <header class="mb-12">
      <h1 class="text-4xl font-extrabold">Lightning-Fast Headless Blog</h1>
      <p class="text-slate-500 mt-2">Bypassing WordPress database queries using pre-generated static JSON feeds.</p>
    </header>

    <main class="space-y-6">
      {posts.map((post) => (
        <article class="p-6 bg-white rounded-lg shadow-sm border border-slate-100 hover:shadow-md transition">
          <h2 class="text-2xl font-bold text-indigo-600 hover:underline">
            <a href={`/blog/${post.slug}`}>{post.title}</a>
          </h2>
          <p class="text-slate-600 mt-3" set:html={post.excerpt} />
          <time class="text-xs text-slate-400 block mt-4">
            Published: {new Date(post.date).toLocaleDateString()}
          </time>
        </article>
      ))}
    </main>
  </body>
</html>

フルスクリーンモードに入る フルスクリーンモードを終了


例B: Next.js(App Router - Incremental Static Regeneration)

Next.jsは静的JSONファイルを自動的にキャッシュし、高効率で提供します。

// app/blog/page.tsx
export const revalidate = 600; // 10分間キャッシュ

interface WordPressPost {
  id: number;
  title: string;
  slug: string;
  excerpt: string;
  date: string;
}

export default async function BlogIndexPage() {
  const res = await fetch('https://your-wordpress-site.com/wp-json/sjec/v1/feed?name=posts', {
    next: { revalidate: 600 }
  });

  if (!res.ok) {
    throw new Error('Failed to fetch static feed');
  }

  const posts: WordPressPost[] = await res.json();

  return (
    <div className="max-w-4xl mx-auto py-12 px-6">
      <h1 className="text-3xl font-bold mb-8">Next.js + Static JSON Feeds</h1>
      <div className="space-y-6">
        {posts.map((post) => (
          <div key={post.id} className="p-6 bg-white border border-slate-200 rounded-lg shadow-sm">
            <h2 className="text-2xl font-bold">
              <a href={`/blog/${post.slug}`} className="text-blue-600 hover:text-blue-800 hover:underline">
                {post.title}
              </a>
            </h2>
            <div 
              className="text-slate-600 mt-2" 
              dangerouslySetInnerHTML={{ __html: post.excerpt }} 
            />
            <span className="text-xs text-slate-400 mt-4 block">
              Published: {new Date(post.date).toLocaleDateString()}
            </span>
          </div>
        ))}
      </div>
    </div>
  );
}

フルスクリーンモードに入る フルスクリーンモードを終了


パフォーマンスベンチマーク

ローカル環境で標準WP REST APIとこのプラグインの応答性を比較しました:

ルーティング / メソッド 平均応答時間 データベース負荷 備考
標準WP REST API 約320 ms 高(WP起動 + MySQLクエリ) 遅く、負荷でクラッシュ
このプラグイン(無料版) 約35 ms ゼロ(0) 保存されたJSONをWP REST経由で提供
このプラグイン(PRO版) <1 ms ゼロ(0) スタンドアロンのapi.php経由でWPコアを完全にバイパス

無料版でも応答遅延を約90%削減し、DBクエリを完全に排除するため、ホスティングサーバーは安定した状態を保てます。


🧼 100%クリーン:トラッキングSDKなし、肥大化なし

WordPressディレクトリの多くの無料プラグインには、ユーザートラッキングデータを収集するためのFreemiusのようなサードパーティマーケティングSDKが含まれています。これにより、管理ダッシュボードに侵入的なアップグレードバナーが表示され、肥大化することがよくあります。

開発者環境を尊重するため、このプラグインの無料版は完全にSDKフリーで構築されています:

  • トラッカーや動的外部スクリプトはありません。
  • 侵入的なアップグレード通知やマーケティングポップアップはありません。
  • 軽量なコードベースで、WordPress.orgの提出ガイドラインに100%準拠しています。

将来的に大規模向けの高性能機能(スタンドアロンapi.phpエンドポイント、複数のカスタムフィード、Webhook自動トリガーなど)が必要になった場合は、PRO版を別途購入してダウンロードできます。


次のステップ

60秒でこのセットアップを試すには、以下をご覧ください:

ヘッドレスWordPressサイトを構築したことはありますか?CORSの解決やAPI応答の高速化にどのようなソリューションを使用しましたか?コメントで議論しましょう!