MENU

ヘッドレスWordPress+Reactでサイトをつくる〜開発環境構築編〜

コーポレートサイトのリニューアルにあたり、「ヘッドレスWordPress」構成を検討することになりました。WordPressをCMS/APIとして使い、フロントエンドはReactとします。検討のために開発環境を構築してみたので、備忘録を兼ねてその手順をまとめました。

サムネイル画像作成の時間短縮のためにAI生成してみましたが、今までとは全く違うテイスト画像になり、いかにもAIでつくったなっていう感じ(汗
まあ、技術ブログなのでご愛嬌ということで…

目次

プロジェクト構成

採用した構成は以下のとおり

  • バックエンド:WordPress(投稿管理、カスタム投稿、ACF Pro、REST API、WPGraphQL)
  • フロントエンド:Vite + React + TypeScript + TailwindCSS v4
  • データ取得:SWR
  • 本番サーバー:レンタルサーバー(エックスサーバー)
  • ローカル開発:WordPress側はwp-env、React側はVite

ディレクトリ構成

corporate-site/
├── cms/                  # WordPress (wp-env)
│   ├── .wp-env.json
│   ├── package.json
│   └── wp-content/
│       ├── themes/
│       │   └── headless-api/  # API専用テーマ
│       ├── plugins/
│       │   └── cors-config/   # CORS設定プラグイン
│       └── uploads/
└── web/                  # React
    ├── .env.local        # 開発用
    ├── .env.production   # 本番用
    ├── package.json
    ├── vite.config.ts
    ├── dist/  # ビルドされたファイル群を格納
    └── src/   # ソースコードを格納

デプロイ構成:完全分離パターン

サブディレクトリ配置やサブドメイン共存も検討しましたが、最終的にはWordPressとReactを完全に別ドメインで分離する構成にしました。

cms.example.com   → WordPress(管理画面・API専用、フロント表示は無効化)
example.com       → React(公開サイト、www付きはリダイレクト)

WordPressのテーマ側で、管理画面とAPIリクエスト以外へのアクセスを template_redirect フックでブロックし、意図的に「フロントエンドを持たないCMS」として運用する形にしています。URLの重複や構造の混乱を避けられるのがメリットです。

WordPress開発環境(wp-env)

ディレクトリ構成の cms/ 側から構築していきます。要するにバックエンドです。

WordPressをインストール

package.jsonと.wp-env.jsonファイルを準備してWordpressをインストールします。

{
  "name": "corporate-cms",
  "scripts": {
    "start": "wp-env start",
    "stop": "wp-env stop",
    "clean": "wp-env clean all"
  },
  "devDependencies": {
    "@wordpress/env": "^10.0.0"
  }
}
{
  "core": "https://ja.wordpress.org/latest-ja.zip",
  "plugins": [
    "./wordpress/plugins/advanced-custom-fields-pro",
    "https://downloads.wordpress.org/plugin/taxonomy-terms-order.zip",
    "https://downloads.wordpress.org/plugin/contact-form-7.zip",
    "https://downloads.wordpress.org/plugin/duplicate-page.zip",
    "https://downloads.wordpress.org/plugin/ewww-image-optimizer.zip",
    "https://downloads.wordpress.org/plugin/flamingo.zip",
    "https://downloads.wordpress.org/plugin/wp-multibyte-patch.zip",
    "https://downloads.wordpress.org/plugin/wp-pagenavi.zip",
    "https://downloads.wordpress.org/plugin/wp-graphql.latest-stable.zip",
    "https://downloads.wordpress.org/plugin/all-in-one-seo-pack.zip",
    "https://downloads.wordpress.org/plugin/siteguard.zip",
    "https://downloads.wordpress.org/plugin/wp-mail-smtp.zip"
  ],
  "config": {
    "WP_DEBUG": true,
    "WP_DEBUG_LOG": true,
    "WP_ENVIRONMENT_TYPE": "local"
  },
  "mappings": {
    "wp-content/uploads": "./wordpress/uploads",
    "wp-content/themes": "./wordpress/themes",
    "wp-content/plugins": "./wordpress/plugins"
  }
}

プラグインは私がよく使用しているものです。

WordPressコア、プラグインは最新を取得できる記述にしています。ADF PROは自動取得できないので事前にファイルを取得しておき、./wordpress/plugins に配置しておきます。

以下をマッピングしています。

マッピング先
wp-content/themes./wordpress/themes
wp-content/plugins./wordpress/plugins
wp-content/uploads./wordpress/uploads

ここまで準備できたら、以下を実行して、いざ!インストール

npm install
npm start

wp-envはデフォルトでadmin / password で管理者を作成します。本番環境へのDB以降を見据えて、初回セットアップ完了後すぐにデフォルトユーザーを変更しておきます。
一度だけ実行すればOK。DBはDockerボリュームに永続化されるので、wp-env destroy しない限り再実行不要です。

npx wp-env run cli wp db query "UPDATE wp_users SET user_login='新ユーザー名' WHERE ID=1"
npx wp-env run cli wp user update 1 --user_email='新ユーザーメールアドレス'
npx wp-env run cli wp user update 1 --user_pass='新ユーザーパスワード'

シェルコマンドでパスワードを扱う場合は、必ずシングルクォートで囲む!(囲み忘れると $ } { ! などシェルにとって意味ある記号が展開されてしまいます)

React開発環境(Vite + TyepScript + Tailwind v4)

次はフロントエンドの開発環境を準備します。ディレクトリ構成の web/ 側 です。

npm create vite@latest web -- --template react-ts

# Which linter to use?
# ESLint
# Install with npm and start now?
# No

cd web
npm install
npm install react-router-dom swr
npm install tailwindcss @tailwindcss/vite
npm install -D @types/node

Tailwind CSS v4 では、これまでとセットアップ方法が変わっているので注意が必要です。

  • @tailwindcss/vite をViteプラグインとして直接組み込む
  • tailwind.config.ts 不要
  • CSSでインポート
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";
import path from "path";

export default defineConfig({
  plugins: [react(), tailwindcss()],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
  server: {
    port: 5173,
    open: true,
  },
  build: {
    outDir: "dist",
    assetsDir: "assets",
    sourcemap: false,
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ["react", "react-dom", "react-router-dom"],
          swr: ["swr"],
        },
      },
    },
  },
});
@import "tailwindcss";

リポジトリ構成

WordPress側(cms/) と React側(web/) は、デプロイ先ドメインも技術スタックも異なるため、Gitリポジトリを分ける構成にしました。

cms/   ← WordPress独立リポジトリ
web/   ← React独立リポジトリ

cms/ 側では基本的なプラグインはURLからの自動ダウンロードなので、Git管理対象は自作のCORS設定プラグインのみとします。

wordpress/plugins/*
!wordpress/plugins/cors-config/
!wordpress/plugins/cors-config/**

本番環境へデプロイ

完全分離構成なので、WordPressとReactは別々にデプロイします。(※デプロイまでは実際には試していません。想定で書いています。予めご了承ください。)

WordPress側 (cms.example.com)

  1. サブドメインを用意しておき、エックスサーバーの「WEordPress簡単インストール」を使ってサーバーにWordPressをインストールします。
  2. FTPでローカルの以下をそれぞれ該当ディレクトリにアップロード
    1. wordpress/theme
    2. wordpress/plugins
    3. wordpress/uploads
  3. 管理画面からプラグインを有効化
  4. テーマを有効化
  5. パーマリンク設定を「投稿名」に変更
  6. wp-config.php に本番用のURLを追記
define('WP_HOME', 'https://cms.example.com');
define('WP_SITEURL', 'https://cms.example.com');
define('WP_DEBUG', false);
define('WP_ENVIRONMENT_TYPE', 'production');

CROS設定は、開発環境用に作った cors-cxonfig プラグインの中で、許可オリジンのリストに本番ドメインを含めておきます。

$allowed_origins = [
    'http://localhost:5173',
    'https://example.com',
    'https://www.example.com',
];

React側(example.com)

ローカルでビルドし、静的ファイルをアップロードするだけです。

cd web
npm run build

dist/配下の中身(index.html・assets/)を、example.comのドキュメントルート直下にアップロードします。

.htaccessは、以下のようにします。

RewriteEngine On

# HTTPS強制
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# www → non-www リダイレクト
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]

# React SPAルーティング
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.html [L]

まとめ

WordPressをヘッドレスCMS化してみました。今回はフロントエンドに Vite + React (CSR、クライアントサイドレンダリング)を選びましたが、SEOを考えるとNext.jsにしてSSR(サーバーサイドレンダリング)やSSG(静的サイト生成)を活用した方が良かったように思いました。

別の機会にNext.js(App Router) + WordPress REST API / GraphQL という組み合わせでやってみようと思います。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次