「WordPressは最初は良かったんですが、今は...」という話を何度聞いたことか。そしていつも続きます。サイトの読み込みに6秒かかる。最後のアップデートの後、お問い合わせフォームプラグインが壊れた。2022年からメンテナンスされていないプラグインに重大な脆弱性がある。元のテーマを作った開発者が音信不通になった。聞き覚えがありませんか?

ここが肝心なところです。WordPressはウェブの40%以上を支えており、それは理由があってのことです。アプローチしやすく、巨大なエコシステムを持ち、多くのビジネスを素早くオンライン化しました。しかし、あなたを始めるためのツールと、あなたと一緒に成長するツールには違いがあります。これを読んでいるなら、おそらくその壁にぶつかっているでしょう。WordPressからヘッドレス Next.js + Supabase アーキテクチャへの本当の移行がどのようなものか、マーケティング版ではなく、実際のエンジニアリング戦略を説明させてください。

目次

WordPress卒業?Next.js + Supabase移行ガイド

WordPressを本当に卒業した兆候

すべての人がWordPressを離れる必要があるわけではありません。それについて率直に言いたいです。個人ブログや地元企業のブロシュアサイトを運営している場合、WordPressと満足のいくテーマ、いくつかのプラグインはおそらくまだ正しい選択です。しかし、WordPressを卒業したことを示す明確な兆候があります。

プラグインの競合が毎月何かを壊している

WooCommerceを更新すると、ページビルダーが壊れます。ページビルダーを更新すると、SEOプラグインが警告を出します。PHPホストが必要とするため8.2に更新すると、3つのプラグインが完全に機能しなくなります。これはバグではありません。それはアーキテクチャです。WordPressプラグインはすべて同じグローバルスコープ、同じフック、同じデータベースを共有します。すべてのプラグインは他のすべてのプラグインとの潜在的な競合です。

私は30個、40個、さらに60個以上のアクティブなプラグインを実行しているWordPressサイトを監査しました。その時点で、あなたはウェブサイトをメンテナンスしていません。ジェンガの塔をメンテナンスしているのです。

パフォーマンスがフルタイムの仕事になった

PageSpeedスコアは30代です。キャッシュプラグイン、画像最適化プラグイン、ミニフィケーションプラグイン、CDNプラグインをインストールしました。すべて他の25個のプラグインによって作成されたパフォーマンスの問題を修正するためです。皮肉は厚いです。

WordPressはすべてのリクエストで動的にページを生成します(キャッシュされていない限り)。各プラグインは独自のCSSとJavaScriptファイルを挿入できます。一般的なWordPressページと人気のプラグインは15〜30個の異なるレンダリングブロッキングリソースをロードします。Googleの2024年Core Web Vitalsデータによると、WordPressサイトは3つのCWV指標すべてに対して33%の合格率を持っていますが、最新のJavaScriptフレームワークで構築されたサイトは52%です。

セキュリティの脆弱性があなたを夜更かしさせる

WPScanの2024年脆弱性データベースでは、その年だけで7,000以上の新しいWordPress脆弱性を追跡しました。大多数はプラグインとテーマにあります。ユーザーデータ、支払い、または何らかの機密情報を処理するサイトを運営している場合、各プラグインは攻撃面です。Patchstackは、2024年のWordPressセキュリティ脆弱性の97%がプラグインから来ていることを報告しました。

本質的に、あなたはプラグインをサイドプロジェクトとして維持する多くの人など、独立した開発者の数十人に対してあなたのセキュリティ体制を信頼しているのです。

あなたの開発チームがそれの上で働くのが嫌い

これは過小評価されています。優れた開発者はもはやWordPressで働きたくありません。PHP-template-spaghetti-with-ACF-fieldsワークフローは、最新のコンポーネントベースの開発と比べて痛いです。エンジニアリングの才能を引き付けて保持しようとしているなら、技術スタックは重要です。

WordPressの税金:プラグイン地獄の本当のコスト

これにいくつかの数字を付けましょう。中規模のWordPressサイト(例えば、ブログ、ユーザーアカウント、カスタム機能を備えたeコマースサイトまたはSaaSマーケティングサイト)の場合、年間の「WordPress税」は通常次のようなものです。

コスト分類 年間推定
プレミアムプラグインライセンス(15-20プラグイン) $1,500 - $4,000
管理型WordPressホスティング(WP Engine、Kinsta) $1,200 - $6,000
セキュリティ監視+クリーンアップ(Sucuri、Wordfence) $300 - $500
パフォーマンス最適化時間(開発者時間) $3,000 - $8,000
プラグイン競合デバッグ(開発者時間) $2,000 - $6,000
アップデートが何かを壊してからの緊急修復 $1,000 - $4,000
WordPressの税金合計 $9,000 - $28,500

単一の新しい機能を作成する前です。それは電気をつけたままにしておくコストです。

Next.js + Supabaseがこのスタックが意味がある理由

ヘッドレスに行く方法は数十あります。Gatsby(Netlifyが買収したため、基本的にメンテナンスモード中)を使用できます。Remix、Astro、またはSvelteKitを使用できます。バックエンドの場合、Firebase、PlanetScale、またはカスタムAPIを使用できます。

しかし、2025年にWordPressから移行しているチームにとって、Next.js + Supabaseは打つのが難しい甘いスポットに当たります。理由は以下の通りです。

Next.js:すべてを実行するフロントエンド

Next.js 15(2024年10月から安定版)は、デフォルトではサーバーコンポーネントを提供します。つまり、動的な柔軟性を備えた静的サイトのパフォーマンスを得ることができます。ブログ投稿を構築時に静的に生成でき、動的ページをサーバーレンダリングでき、同じアプリでインタラクティブなコンポーネントをクライアントレンダリングできます。

WordPressから移行しているチームにとって、重要な利点は以下の通りです。

  • 組み込み画像最適化 - 2-3個のWordPressプラグインを置き換えます
  • 自動コード分割 - 各ページは必要なJSのみをロードします
  • エッジミドルウェア - CDNレベルでリダイレクト、認証、A/Bテストを処理します
  • 増分静的再生成(ISR) - 完全な展開なしに個々のページを再構築します
  • App Routerとサーバーコンポーネント - クライアント側のJavaScriptを大幅に削減します

Social Animalで多くのNext.jsプロジェクトを構築します(Next.js開発機能を確認してください)、WordPressに対するパフォーマンス差は一貫して劇的です。

Supabase:バックエンドWordPressが欲しかったもの

Supabaseは、PostgreSQLに基づいて構築されたオープンソースのFirebaseの代替です。それはあなたに与えます:

  • スキーマから自動生成されたREST APIとGraphQL APIを備えた完全なPostgresデータベース
  • 組み込み認証(メール、OAuth、マジックリンク、SSO)
  • きめ細かいアクセス制御のための行レベルのセキュリティポリシー
  • WebSocket経由のリアルタイムサブスクリプション
  • サーバーレスバックエンドロジック用のエッジ機能
  • CDN配信付きのファイルアップロード用ストレージ

WordPress移行の具体的には、Supabaseは、WordPressがMySQLを使用し、データモデルがPostgreSQLに驚くほどよくマップされるため素晴らしいです。カスタムポストタイプはテーブルになります。ポストメタはJSONB列になります。ユーザーデータはほぼ1対1でマップします。

Supabaseの無料層には、500MBのデータベース、1GBのストレージ、認証で50,000の月次アクティブユーザーが含まれます。彼らの$25/月のProプランは、ほとんどの本番サイトをカバーしています。それだけでも、管理型WordPressホスティングに支払っている$30-$100/月と比較してください。

WordPress卒業?Next.js + Supabase移行ガイド - アーキテクチャ

移行戦略:フェーズごと

ここは私が数十のWordPress移行で改善してきたアプローチです。週末プロジェクトではありません。サイトの複雑さによって4~12週間を予算化してください。ただし、フェーズに従えば、それは予測可能で低リスクです。

フェーズ1:監査とアーキテクチャ(第1週)

単一の行のコードを書く前に:

  1. 完全なプラグインリストをエクスポート wp plugin list --status=active を使用(WP-CLI)
  2. すべてのプラグインを新しいスタックの置き換えにマップ
  3. すべてのポスト、ページ、分類法、カスタムポストタイプを含む、完全なURL構造をエクスポート
  4. すべてのフォーム、統合、およびサードパーティ接続を文書化
  5. テーマのfunctions.phpに存在するカスタム機能を特定

プラグインマッピング演習は重要です。一般的な置き換えは次のようなものです:

WordPressプラグイン ヘッドレス置き換え
Yoast SEO Next.js組み込みメタデータAPI + generateMetadata()
WP Super Cache / W3 Total Cache 不要(デフォルトで静的)
Wordfence / Sucuri Supabase RLS + Vercelの組み込みDDoS保護
Contact Form 7 / Gravity Forms React Hook Form + Supabase Edge Function
WooCommerce Saleor、Medusa.js、またはShopify Storefront API
ACF / カスタムフィールド 型付きスキーマを持つSupabaseテーブル
WP Migrate DB 1回限りのSupabase移行スクリプト
Smush / ShortPixel Next.js Imageコンポーネント(組み込み)
Elementor / WPBakery Reactコンポーネント(あなたは彼らを逃しません)

フェーズ2:新しいスタックをセットアップ(第2週)

# Next.jsプロジェクトを作成
npx create-next-app@latest my-site --typescript --tailwind --app --src-dir

# Supabaseをインストール
npm install @supabase/supabase-js @supabase/ssr

# 環境変数をセットアップ
cp .env.example .env.local

あなたの.env.local

NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key

すぐにVercelに展開します。はい、意味のあるものを構築する前です。初日から住んでいるプレビューURLを持つことはあなたがどのように機能するかを変えます。ステークホルダーは進捗を見ることができ、展開の問題を早期に捕捉します。

データ移行:WordPressからコンテンツを取り出す

ここは、ほとんどの移行ガイドが手を振る場所です。具体的にしましょう。

ステップ1:WordPressデータをエクスポート

組み込みのWordPress XMLエクスポートを使用しないでください。不完全で構造が悪いです。代わりに、WP-CLIと直接データベースクエリを使用します:

# ポストをJSONとしてエクスポート
wp post list --post_type=post --format=json --fields=ID,post_title,post_content,post_excerpt,post_date,post_status,post_name > posts.json

# ページをエクスポート
wp post list --post_type=page --format=json --fields=ID,post_title,post_content,post_excerpt,post_date,post_status,post_name > pages.json

# カスタムポストタイプをエクスポート
wp post list --post_type=your_cpt --format=json > cpt.json

# ポストメタをエクスポート(ACFフィールドなど)
wp eval 'global $wpdb; $results = $wpdb->get_results("SELECT post_id, meta_key, meta_value FROM wp_postmeta WHERE meta_key NOT LIKE \"_%\""); echo json_encode($results);' > postmeta.json

ステップ2:Supabaseに変換とロード

移行スクリプトを書いてください。私はこれにはTypeScriptを好みます:

import { createClient } from '@supabase/supabase-js'
import posts from './exports/posts.json'

const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_ROLE_KEY!
)

async function migratePosts() {
  for (const post of posts) {
    const { error } = await supabase.from('posts').insert({
      wp_id: post.ID,
      title: post.post_title,
      slug: post.post_name,
      content: convertWpContentToMdx(post.post_content),
      excerpt: post.post_excerpt,
      published_at: post.post_date,
      status: post.post_status === 'publish' ? 'published' : 'draft',
    })
    
    if (error) console.error(`Failed to migrate post ${post.ID}:`, error)
  }
}

function convertWpContentToMdx(html: string): string {
  // turndownまたはrehypeを使用してWordPress HTMLをMDXに変換
  // ショートコード、埋め込み、Gutenbergブロックを処理
  // これは移行の複雑さの80%が存在する場所です
}

convertWpContentToMdx関数は、最も時間を費やす場所です。WordPressコンテンツはHTML、ショートコード、Gutenbergブロックコメント、および埋め込みoEmbed URLの混乱です。turndownのようなライブラリは基本的なHTML-to-Markdown変換を処理しますが、ショートコードとブロックのカスタムルールが必要になります。

ステップ3:メディアを移行

import { createClient } from '@supabase/supabase-js'
import fetch from 'node-fetch'

async function migrateMedia(mediaItems: any[]) {
  for (const item of mediaItems) {
    const response = await fetch(item.source_url)
    const buffer = await response.buffer()
    
    const { error } = await supabase.storage
      .from('media')
      .upload(`uploads/${item.slug}.${item.mime_type.split('/')[1]}`, buffer, {
        contentType: item.mime_type,
      })
    
    if (error) console.error(`Failed to upload ${item.slug}:`, error)
  }
}

Next.jsで新しいフロントエンドを構築

Supabaseにデータを入れたら、フロントエンドの構築は楽しい部分です。Next.js App Routerを使用した典型的なブログ投稿ページは以下の通りです:

// src/app/blog/[slug]/page.tsx
import { createClient } from '@/lib/supabase/server'
import { notFound } from 'next/navigation'
import { MDXRemote } from 'next-mdx-remote/rsc'

export async function generateMetadata({ params }: { params: { slug: string } }) {
  const supabase = createClient()
  const { data: post } = await supabase
    .from('posts')
    .select('title, excerpt, og_image')
    .eq('slug', params.slug)
    .single()

  if (!post) return {}

  return {
    title: post.title,
    description: post.excerpt,
    openGraph: { images: [post.og_image] },
  }
}

export default async function BlogPost({ params }: { params: { slug: string } }) {
  const supabase = createClient()
  const { data: post } = await supabase
    .from('posts')
    .select('*')
    .eq('slug', params.slug)
    .eq('status', 'published')
    .single()

  if (!post) notFound()

  return (
    <article className="prose lg:prose-xl mx-auto">
      <h1>{post.title}</h1>
      <time dateTime={post.published_at}>
        {new Date(post.published_at).toLocaleDateString()}
      </time>
      <MDXRemote source={post.content} />
    </article>
  )
}

キャッシュプラグイン、パフォーマンスプラグイン、SEOプラグインはないことに注意してください。メタデータAPIはSEOを処理します。サーバーコンポーネントはパフォーマンスを処理します。CDNはキャッシュを処理します。すべて組み込まれています。

バックエンドとしてのSupabaseのセットアップ

Supabaseスキーマは、WordPressの汎用wp_posts / wp_postmeta構造ではなく、実際のデータニーズの周りに設計する必要があります。ここはより清潔なスキーマです:

-- ポストテーブル
create table posts (
  id uuid default gen_random_uuid() primary key,
  title text not null,
  slug text unique not null,
  content text,
  excerpt text,
  featured_image text,
  status text default 'draft' check (status in ('draft', 'published', 'archived')),
  author_id uuid references auth.users(id),
  published_at timestamptz,
  created_at timestamptz default now(),
  updated_at timestamptz default now(),
  metadata jsonb default '{}'
);

-- カテゴリ
create table categories (
  id uuid default gen_random_uuid() primary key,
  name text not null,
  slug text unique not null,
  description text
);

-- 行レベルセキュリティ
alter table posts enable row level security;

create policy "Published posts are viewable by everyone"
  on posts for select
  using (status = 'published');

create policy "Authors can manage their own posts"
  on posts for all
  using (auth.uid() = author_id);

metadata jsonb列はあなたの脱出ハッチです。独自の列に値しないカスタムフィールドはそこに存在できます。インデックス付き、クエリ可能、無限に柔軟です。プラグインのようなACFフィールドですが、プラグインなしです。

認証とユーザーデータの処理

WordPressサイトにユーザーアカウントがある場合、Supabase Authは移行をきれいに処理します。パスワードハッシュを移行することはできません(WordPressはphpassを使用し、Supabaseはbcryptを使用します)が、以下を実行できます:

  1. ユーザーメールとプロフィールをSupabaseにインポート
  2. 最初のログイン時にすべてのユーザーに「パスワードをリセット」フローをトリガー
  3. またはマジックリンク認証を使用して、パスワードが全く必要ないようにします

Supabaseは、メール/パスワード、Google、GitHub、Apple、その他の数十のOAuthプロバイダをサポートしています。プラグインは必要ありません。

SEO保持:構築したものを失わない

これは交渉不可能です。ぐちゃぐちゃになった移行は、一晩で何年ものSEO資産を破壊することができます。ここはチェックリストです:

  1. すべての古いURLを新しいURLにマップします。 WordPressはデフォルトで/2024/01/post-title/を使用します。新しいサイトは/blog/post-titleを使用するかもしれません。すべての古いURLには301リダイレクトが必要です。

  2. Next.jsにリダイレクトを実装:

// next.config.js
module.exports = {
  async redirects() {
    return [
      // 日付ベースのWordPress URLをクリーンなスラッグに
      {
        source: '/:year(\\d{4})/:month(\\d{2})/:slug',
        destination: '/blog/:slug',
        permanent: true,
      },
      // カテゴリページ
      {
        source: '/category/:slug',
        destination: '/blog/category/:slug',
        permanent: true,
      },
    ]
  },
}
  1. すべてのメタタイトル、説明、および構造化データを保持します。 移行前にYoastからエクスポートします。
  2. 起動直後に新しいサイトマップをGoogle Search Consoleに送信します。
  3. ロールバック用に古いサイトをサブドメイン(old.yoursite.com)で30日間実行し続けます。

パフォーマンスベンチマーク:ビフォー・アフター

ここはSocial Animalでの移行からの実際の数字です(これらは2024-2025年の12の移行プロジェクト全体の平均です):

指標 WordPress(前) Next.js + Supabase(後) 改善
Lighthouseパフォーマンススコア 38 94 +147%
最大のコンテンツフルペイント(LCP) 4.2s 0.9s -79%
最初のインプット遅延(FID) 180ms 12ms -93%
累積レイアウトシフト(CLS) 0.25 0.02 -92%
最初のバイトまでの時間(TTFB) 1.8s 0.15s -92%
ページの総重量 3.2MB 420KB -87%
HTTPリクエスト 47 8 -83%

これらは厳選されていません。彼らは一貫しています。30以上のプラグインを削除すると、それぞれが独自のCSSとJSを挿入し、動的PHPレンダリングをグローバルCDN上の静的/サーバーレンダリングされたReactコンポーネントで置き換えると、結果は予測可能です。

あなたのプロジェクトがこの種の結果がどのようなものであるかについて興味がある場合、私たちの価格ページは、ヘッドレス移行プロジェクトが通常何を費やすかを分解します。

コスト比較:WordPressとヘッドレススタック

WordPress(年間) Next.js + Supabase(年間)
ホスティング $1,200 - $6,000(WP Engine/Kinsta) $0 - $240(Vercel Pro)
データベース/バックエンド ホスティングに含まれます $0 - $300(Supabase Pro)
プラグインライセンス $1,500 - $4,000 $0
セキュリティツール $300 - $500 $0(組み込み)
CDN $0 - $600 $0(Vercelに含まれます)
メンテナンス開発者時間 $6,000 - $18,000 $1,000 - $4,000
合計 $9,000 - $29,100 $1,000 - $4,540

ヘッドレススタックは、年間の運営コストを70~85%削減します。移行自体には明らかに前払いコストがあります。複雑さによっては、プロのビルドでは通常$15,000~$60,000です(具体的にはヘッドレスCMS開発サービスを参照してください)。しかし、それは6~18ヶ月以内にまかなわれます。より良いパフォーマンスとSEOの収益への影響を考慮する前に、運営コストの削減を通じて。

FAQ

移行後、コンテンツを管理するためにReact/Next.jsを学ぶ必要がありますか?

いいえ。ほとんどのチームはNext.jsをSanity、Contentful、またはその純粋なヘッドレスCMS(REST APIを介して)として使用されるWordPressなどのヘッドレスCMSと組み合わせます。コンテンツ編集者はコードに触れません。彼らはきれいな編集インターフェースを取得し、フロントエンドはAPIを介してコンテンツを引き出します。あなたのチームがすでに知っているWordPress編集者を保ちたい場合、あなたは絶対にできます。WordPressフロントエンドを削除し、コンテンツバックエンドとしてそれを使用するだけです。

典型的なWordPressからNext.jsへの移行にはどのくらいの時間がかかりますか?

コンテンツに焦点を合わせたサイトで、ブログと標準的なページ:4~6週間。eコマース、ユーザーアカウント、カスタムポストタイプ、複雑な機能を備えたサイト:8~14週間。最大の変数はコンテンツの複雑さです。ショートコード依存コンテンツが重くまたは深くカスタマイズされたGutenbergブロックを含むサイトには、クリーンに移行するのに時間がかかります。

移行中にGoogle ランキングが失われますか?

リダイレクトを適切に処理すれば、そうではありません。301リダイレクトは、リンク資産の約90~99%を保持します。移行後の最初の1~2週間は通常、小さな落ち込みが見られます(Googleはクロールする必要があります)。その後、より良いCore Web Vitalsスコアのため、ランキングが向上します。重要なことは、すべてのURLをマップし、起動するまでリダイレクトマップが完成するまで起動しないことです。

Supabaseは高トラフィックサイトの本番環境対応ですか?

はい。SupabaseはAWSインフラストラクチャで実行され、数百万のリクエストを処理する企業によって本番環境で使用されています。彼らのデータベースは、PostgreSQLにすぎません。おそらく存在する最も実証済みのデータベース。2025年の時点で、Supabaseは100万以上のデータベースを提供し、1日数十億のAPIリクエストを処理しています。追加のスケールのために、彼らのPro($25/月)およびTeam($599/月)プランは専用リソースと優先サポートを含みます。

この スタックにWooCommerceを移行できますか?

あなたができますが、eコマースは大幅な複雑さを追加します。ほとんどのチームがWooCommerceから移行する場合、Shopify(Next.jsフロントエンドでStorefront APIを使用)またはMedusa.jsやSaleorなどのオープンソースソリューションのいずれかに移動します。Supabaseは製品カタログと注文管理を処理できますが、チェックアウト、支払い処理、在庫管理、および税計算を自分で構築する必要があります。ほとんどの企業にとって、専用のeコマースバックエンドを使用し、Next.jsに接続することは、より理にかなっています。

WordPressマルチサイトについてはどうですか。このスタックはそれを置き換えることができますか?

絶対に。Next.jsはミドルウェアと動的ルーティングを使用した優れたマルチテナントアーキテクチャサポートを持っています。Supabaseの行レベルセキュリティにより、テナント別にデータを分割することが簡単になります。テナント固有のルーティングを備えた50以上のサイトを持つWordPressマルチサイトネットワークを単一のNext.jsアプリケーションに移行しました、運営の単純化は途方もありませんでした。

それでもCMSが必要ですか、またはSupabaseだけを使用できますか?

Supabaseはテーブルエディタを提供します。開発者にとっては機能しますが、コンテンツ編集者は通常、より洗練されたものが必要です。最も一般的なアプローチは:(1)コンテンツにはSanityやStoryblokなどの専用ヘッドレスCMSを使用し、アプリケーションデータにはSupabaseを使用、(2)Next.js + Supabase Authを使用して単純な管理UIを構築、または(3)Wordpressを純粋なコンテンツレスバックエンドとして保持。オプション1はコンテンツが多いサイトで最も人気があります。オプションを検討している場合、Astro開発ヘッドレスCMSページでトレードオフを分解します。

移行がうまくいかない場合、WordPressにロールバックできますか?

はい。移行プロセス全体でWordPressサイトをサブドメインで実行し続ける必要があります。DNS レベル切り替え(AレコードまたはCNAMEを変更)を使用すると、数分でロールバックできます。新しいサイトの起動後、古いWordPressインスタンスを少なくとも30日間実行し続けることをお勧めします。すべてのリダイレクトが機能し、検索ランキングが安定し、すべての機能が確認された後にのみ廃止してください。移行を計画する際にロールバック手順を含める場合は、チームに連絡してください。ここは落とし穴を知るほど多くをしています。