Next.jsやAstroのようなモダンなフロントエンドフレームワークでヘッドレスWordPressサイトを構築することに決めたとしましょう。素晴らしい開発者体験のように聞こえますが、2つの有名な障害にぶつかるまでです:
-
CORS地獄:ローカルの開発サーバーを
http://localhost:4321またはhttp://localhost:3000で立ち上げ、fetchリクエストを実行すると... ブラウザコンソールが赤いCORSポリシーエラーで溢れます。 - 遅い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セットアップ
- 公式WordPressプラグインディレクトリからStatic JSON Export & CORS Whitelistを検索してインストールします。
- ダッシュボードのJSON Export CORS設定ページを開きます。
- CORS Allowed Originsリストに開発用URL(例:
http://localhost:4321またはhttp://localhost:3000)を追加します。 - 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プラグイン: WordPress.orgのStatic JSON Export & CORS Whitelist
- 🚀 すぐに使えるボイラープレート: GitHubのAstro Headless WordPress Starter Template
ヘッドレスWordPressサイトを構築したことはありますか?CORSの解決やAPI応答の高速化にどのようなソリューションを使用しましたか?コメントで議論しましょう!
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.