カルキチブログ

WordPressのプラグインのUIをViteでビルドしたReactで構築する方法

ゴールデンウィーク中にふと、ViteでビルドしたReactをWordPressの管理画面上で動かしたい衝動に駆られました。

色々調査した結果なんとか動かすことに成功したので、今回はWordPressのプラグインのUIをViteでビルドしたReactで構築する方法について、解説していこうと思います。

https://twitter.com/karukichi_yah/status/1523187259188555778

今回の記事は、以下の知見がある方向けに執筆しました。

  • React・Viteの基本的な知識
  • フロントのビルド周りの基本的な知識
  • PHPの基本的な知識
  • WordPressの関数・フックなどの基本的な知識

事前準備

環境構築を行う前に、いくつかの事前準備が必要になります。

1, バックエンド側のセットアップ

wp-content/pluginsディレクトリ配下に適当なディレクトリを作って、以下のファイルの作成を行ってください。

<?php
/*
  Plugin Name: WP Plugin Vite React sample.
  Plugin URI:
  Description: React Vite WordPress Plugin Starter
  Version: 1.0.0
  Author: Soejima-Karukichi
  Author URI: https://github.com/Yota-K
  License:
 */

// PHPファイルを外部から直接実行されるのを防ぐために記述する必要がある
if (!defined('ABSPATH')) exit;

require_once(__DIR__ . '/class-create-admin-page.php');
<?php
if (!class_exists('CreateAdminPage')):

class CreateAdminPage {
  public function __construct()
  {
     // 念には念を入れて管理画面でしかインスタンス生成時に処理を行わないようにする
    if (is_admin()) {
      add_action('admin_menu', [$this, 'admin_menu']);
    }
  }

  // メインメニュー
  public function admin_menu()
  {
    add_menu_page(
      'sample', /* ページタイトル*/
      'sample', /* メニュータイトル */
      'manage_options', /* 権限 */
      'sample-plugin', /* ページを開いたときのurl */
      [$this, 'home_page'], /* メニューに紐づく画面を描画するcallback関数 */
      'dashicons-media-text', /* アイコン */
      3, /* 表示位置の優先度 */
    );
  }

  // ホーム画面
  public function home_page()
  {
     // Reactで構築したUIをレンダリングするための要素を定義してechoで出力
    echo '<div id="vite-react-sample"></div>';
  }
}

new CreateAdminPage();

endif;

添付画像のようにサイドバーに「Sample」というメニューが表示されて、SampleをクリックするとWPの管理画面上に<div id="vite-react-sample"></div>という要素が生成されていたら正常に動作しています。

2, フロント環境のセットアップ

先ほど作ったPHPファイルがあるディレクトリで、以下のコマンドを実行してください。

yarn create vite front --template react-ts

インストールが完了したら、以下のコマンドを実行してください。

cd front/
yarn install

ライブラリのインストールが完了したら、yarn devで開発環境を立ち上げてください。

正しい手順で環境構築できていたら、http://localhost:3000で、開発環境にアクセスできるはずです。

実際に動かしてみる

では実際に動かす方法について解説していきます。

ViteでビルドしたReactをWPの管理画面上で動かすために必要な作業は主に2つです。

  • ビルド周りの設定を変更する
  • ビルドしたCSS・JSを開発したプラグインの画面でのみ読み込ませるようにする

では順を追って解説していきます。

1, ビルド周りの設定を変更する

ビルド周りの設定がデフォルトの状態だと、CSSやJSのファイル名と拡張子の間にハッシュ値が付与されてしまうため、WP側でCSSやJSを読み込ませようとしてもうまくいきません。

<script type="module" crossorigin src="/assets/index.c115a8ef.js"></script>
<link rel="stylesheet" href="/assets/index.62f502b0.css">

また、コンポーネント内で使用しているSVGや画像なども正常に読み込むことができないので、ビルド周りの設定を変更する必要があります。

ビルド周りの設定はvite-config.tsで変更することができます。

編集可能なオプションは公式ドキュメントを確認してください。

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  base: '/wp-content/plugins/wp-plugin-vite-react-sample/front/dist/',
  plugins: [react()],
  build: {
    rollupOptions: {
      output: {
        entryFileNames: `assets/[name].js`,
        chunkFileNames: `assets/[name].js`,
        assetFileNames: `assets/[name].[ext]`
      }
    }
  }
})

やっていることとしては、baseオプションでビルドされる本番環境で配信される際のベースとなるパブリックパスをプラグインが配置されているディレクトリに変更して、buildオプションで出力されるCSS・JSのハッシュ値を削除しているという感じです。

ハッシュ値の削除方法はViteのリポジトリのイシューに載っていました。

設定完了後に、yan buildするとfrontというディレクトリ内にdistディレクトリが作成されるので、distディレクトリ内に出力されたindex.htmlを確認してみましょう。

以下のようなHTMLファイルが出力されていれば、ビルド周りの設定の変更は上手くできています。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/wp-content/plugins/wp-plugin-vite-react-sample/front/dist/assets/favicon.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
    <script type="module" crossorigin src="/wp-content/plugins/wp-plugin-vite-react-sample/front/dist/assets/index.js"></script>
    <link rel="stylesheet" href="/wp-content/plugins/wp-plugin-vite-react-sample/front/dist/assets/index.css">
  </head>
  <body>
    <div id="vite-react-sample"></div>
  </body>
</html>

一応補足しておきますが、今回必要なのはViteでビルドされたCSSとJS、ReactのSVGアイコンのみなので、distディレクトリ配下に出力されたHTMLファイルは今回は使用しません。

これでフロントの設定は完了です。

2, ビルドしたリソースをプラグインで読み込む

次にdistディレクトリに出力されたCSS・JSをプラグイン側で読み込む設定を行います。

以下サンプルコードです。

<?php
if (!class_exists('CreateAdminPage')):

class CreateAdminPage {
  public function __construct()
  {
    if (is_admin()) {
      add_action('admin_menu', [$this, 'admin_menu']);
        // 以下追記
      add_action('admin_enqueue_scripts', [$this, 'include_home_resources']);
    }
  }

  // メインメニュー
  public function admin_menu()
  {
    add_menu_page(
      'sample', /* ページタイトル*/
      'sample', /* メニュータイトル */
      'manage_options', /* 権限 */
      'sample-plugin', /* ページを開いたときのurl */
      [$this, 'home_page'], /* メニューに紐づく画面を描画するcallback関数 */
      'dashicons-media-text', /* アイコン */
      3, /* 表示位置の優先度 */
    );
  }

  // 以下追記
  // ホーム画面で使用するCSS・JSを読み込ませる
  public function include_home_resources()
  {
    $plugin_url = plugin_dir_url(__FILE__);
    $current_page_url = (empty($_SERVER['HTTPS']) ? 'http://' : 'https://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

    // プラグインのホーム画面でのみCSS・JSを読み込ませる
    if (preg_match('/admin\.php\?page=sample-plugin$/u', $current_page_url)) {
      wp_enqueue_style('sample-plugin-css', $plugin_url . 'front/dist/assets/index.css', [], wp_rand());
      wp_enqueue_script('sample-plugin-js', $plugin_url . 'front/dist/assets/index.js', ['jquery', 'wp-element'], wp_rand(), true);
    }
  }

  // ホーム画面
  public function home_page()
  {
    echo '<div id="vite-react-sample"></div>';
  }
}

new CreateAdminPage();

endif;

WPの管理画面で独自のCSS・JSを読み込むためには、admin_enqueue_scriptsというフックを使用します。

このフックは名前通り、WordPressの管理画面上で独自のCSS・JSを読み込むことができるフックです。

今回のサンプルプラグインはクラスベースで記述しているのでadd_actionでフックを定義する際は、第2引数の配列に$thisと呼び出す関数名を記述するのも忘れないようにしましょう。

<?php
function include_home_resources()
  {
    $plugin_url = plugin_dir_url(__FILE__);
    $current_page_url = (empty($_SERVER['HTTPS']) ? 'http://' : 'https://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

    // プラグインのホーム画面でのみCSS・JSを読み込ませる
    if (preg_match('/admin\.php\?page=sample-plugin$/u', $current_page_url)) {
      wp_enqueue_style('sample-plugin-css', $plugin_url . 'front/dist/assets/index.css', [], wp_rand());
      wp_enqueue_script('sample-plugin-js', $plugin_url . 'front/dist/assets/index.js', ['jquery', 'wp-element'], wp_rand(), true);
    }
  }
   add_action('admin_enqueue_scripts', 'include_home_resources');

include_home_resourcesという関数でViteでビルドしたCSSやJSを読み込ませているのですが、表示されているパスが作成したプラグインのパスの時のみCSSやJSを読み込ませるようにしています。

プラグイン以外の画面で不要なCSSやJSを読み込ませないためという意図もありますが、作成したプラグインの画面のみで読み込ませないと記事編集画面でエラーが発生したので、プラグイン画面のみで読み込ませるようにしています。

エラーが発生した原因ですが、Gutenbergのブロックエディタを動作させるためにWP側が元々読み込んでいるReactとバッティングしたからだと考えられます。

ビルドしたリソースをプラグインで読み込む処理を書いたら、ブラウザをリロードして確認してみましょう。

以下のような画面が表示されていたら無事成功です。

まとめ

まとめます。

  • ViteでビルドしたReactをWordPressの管理画面上で動かすことはできる
  • ViteでビルドしたReactをWordPressで動かす際は、ビルド設定の変更が必須

ネタもネタ、全く需要ないと思いますが、ViteでビルドしたReactでWPのプラグインのUIを作ってみたい人は参考にしてみてください!

今回紹介したコードのサンプルリポジトリも用意したので、興味ある方はぜひご覧ください。

https://github.com/Yota-K/wp-plugin-vite-react-sample

おまけ

GWだったので、久しぶりにネタ系の技術記事を書きました。

時間に追われることなく、好きなように自由にコード書けるっていいなと改めて感じました。

その他補足としては、テーマによってはテーマが独自に読み込んでいるCSSと、React側のCSSのコンフリクトが頻発しまして、解消がめちゃくちゃ面倒でした。

基本的にはReact側でスタイルの優先度を変更すれば適用されますが、React側で優先度を上げても解消できないものもいくつかありました。

そういったものに関しては、プラグインのディレクトリにreset.cssを作成することで解決可能です。