WordPress+Nuxt(SSG)+GitHub Actionsでレンタルサーバーに自動デプロイする方法

最近Nuxtでサイトを作り始めて、SSGで生成したものを自動でサーバーにアップロードできないかなと思い、色々試行錯誤して動作するまでをまとめました。

【2022/03/03 20:30 追記】

GitHubでテンプレート公開しました!
https://github.com/tnyk35/wst-wp-nuxt-template

実際にビルドしてできてるものはこちらです!
https://tnyk.jp/sample-wp-nuxt/

構成

まずは構成から

  • レンタルサーバー:XServer
  • コンテンツ管理:WordPress
    WP RESTを利用。サブドメインAにWordPressをインストール済み。
  • ビルド&サーバー同期は、GitHub Actionsを利用。生成したページを、XServerに同期
  • Nuxt.jsのSSGを利用して実装
  • node v16.4.0
  • Nuxt v2.15.8

手順

ざっくり3つの手順になります。

  • (1)Nuxtでサイトを作る&GitHub Actionsのワークフローを作成し、GitHubにpushしておく
  • (2)GitHubのSecretsで必要な情報を登録
  • (3)WPで記事作成&更新時に、アクションフックでGitHub Actionsのワークフローを実行させる

手順に沿ってそれぞれ解説していきます。

(1)Nuxtでサイトを作る&GitHub Actionsのワークフローを作成し、GitHubにpushしておく

Nuxtでのサイト作りについては端折りますが、.gitのあるディレクトリで各ファイルを設置して作成を進めましょう。(リポジトリの直下に置く)

※レンタルサーバーによって海外IPアドレスからのアクセスを拒否するようになっているところがありますので、解除しておきましょう!

ファイルツリー構造だとこんな感じで配置してます!

.
├── .github
│  └── workflows
│     └── save.yml ←これを作成する
├── README.md
├── assets
├── components
├── layouts
├── nuxt.config.js
├── package-lock.json
├── package.json
├── pages
├── static
├── store
├── tailwind.config.js
└── tsconfig.json

次に、GitHub Actionsのワークフローを作成しましょう!

今回は、 「.github/workflows/save.yml」 とします。(上のツリーを参考に!)

以下内容です。

name: save

on:
  repository_dispatch:
    types: [after_saving_wordpress]
  # push:
  #   branches:
  #     - master


jobs:
  deploy:
    runs-on: ${{ matrix.os }}

    strategy:
      matrix:
        os: [ubuntu-latest] # OSの種類とバージョン
        node: [16.4] # nodeのバージョン

    steps:
      - name: Checkout 🛎
        uses: actions/checkout@v2

      - name: Setup node env 🏗
        uses: actions/setup-node@v2.1.5
        with:
          node-version: ${{ matrix.node }}
          check-latest: true

      - name: Cache node_modules 📦
        uses: actions/cache@v2.1.4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: Install dependencies 👨🏻‍💻
        run: npm ci --prefer-offline --no-audit

      - name: Nuxt Generate
        run: npm run generate

      - name: FTP Deploy
        uses: SamKirkland/FTP-Deploy-Action@4.3.0     # FTPデプロイ用のアクション(https://github.com/SamKirkland/FTP-Deploy-Action)
        with:
          server: ${{ secrets.FTP_SERVER }}       # FTPのホスト名(サーバー名やIPアドレス)
          username: ${{ secrets.FTP_USER }}       # FTPのユーザー名
          password: ${{ secrets.FTP_PASSWORD }}   # FTPのパスワード
          local-dir: ./dist/                      # アップロード元のパス(基本的には、npm run generate で出力されるディレクトリを指定)
          server-dir: ${{ secrets.DEPLOY_DIR }}   # アップロード先のリモートパス

こちらを作成したら、コミット&プッシュしておきましょう!

内容を簡単に上から解説すると、

「repository_dispatch」
ここにはデプロイさせる条件を書きます。
push部分のコメントアウトを外すと、branchesで指定したブランチが、pushされたタイミングで、GitHub Actionsが実行されるようになります。

「name: Checkout 🛎」
「name: Setup node env 🏗」
「name: Cache node_modules 📦」
「name: Install dependencies 👨🏻‍💻」

上記4つはお決まりのパターンなので端折ります。(バージョン古いかも)

「name: Nuxt Generate」
npm run generateしてページ生成してます。

「name: FTP Deploy」
FTPにアップロードする設定を記載します。 ${{ secrets.FTP_SERVER }} などは、GitHubのSecretsというのを登録することで読み込んでくれるようになります。こちらは次の章で解説します。

ちなみにFTPではなくRsyncを利用した方法もあるんですが、エックスサーバーだとうまく動かなかったので無難にFTPをつかっておくのが良いです。(ConoHaWingサーバーだとrsync動きました。)

(2)GitHubのSecretsで必要な情報を登録

次にSecretsの登録をしていきましょう!

まずは、GitHubで対象のリポジトリのSettingsにアクセスし、「Secrets > Actions」を開きましょう。(画像赤枠部分)

ページURLはこんな感じになります→https://github.com/ユーザー名/リポジトリ名/settings/secrets/actions

次に、画像赤枠の「New repository secret」ボタンを押して以下4項目を登録してください。

  • DEPLOY_DIR
    アップロード先のディレクトリを入力 例:/tnyk.jp/public_html/
  • FTP_SERVER
    FTPのサーバー名を入力 例:[XXX].xserver.jp
  • FTP_USER
    FTPのユーザー名を入力 サブFTP利用する場合、サブFTPアカウントに設定したユーザーID(@以降も含みます)
  • FTP_PASSWORD
    FTPのパスワードを入力 サブFTPを作成時に設定したパスワード。サブFTPアカウントに設定したFTPパスワード

これで、GitHub Actionsを実行した際に、${{ secrets.FTP_SERVER }} などの値を設定した状態で実行するようになります。

(3)WPで記事作成&更新時に、アクションフックでGitHub Actionsのワークフローを実行させる

上画像赤枠の「Generate new token」ボタンを押して、以下の項目にチェックを入れて登録してください。

ここでは、有効期限なしにしています。
※セキュリティのリスクを考えると、有効期限を設定したり、定期的にトークンを再生成したほうがいいです。

登録が完了すると、アクセストークンが発行されるので、必ずメモっておいてください。

次に、WordPressのfunctions.phpの一番下に以下を追記してください。


/* -------------------------- */
/* GitHub ActionsへのHookを設定 */
/* -------------------------- */
add_action('publish_post', 'after_saving_wordpress', 10, 2); // 「投稿」の記事が公開されたときに実行
add_action('publish_to_draft', 'publish_to_saving_wordpress', 10, 1); // 記事のステータスが「公開」から「下書き」になったときに実行
add_action('publish_to_trash', 'publish_to_saving_wordpress', 10, 1); // 記事のステータスが「公開」から「ゴミ箱」に入ったときに実行

function after_saving_wordpress($post_id, $post) {
  dispatch_github_actions();
  return true;
}

function publish_to_saving_wordpress($post) {
  if ($post->post_type === 'post') {
    dispatch_github_actions();
    return true;
  }
  return false;
}

/* -------------------------- */
/* GitHub ActionsのHookを実行 */
/* -------------------------- */
function dispatch_github_actions() {
  $token = '取得したアクセストークンを入れる';
  $url = 'https://api.github.com/repos/ユーザー名を入れる/リポジトリ名を入れる/dispatches';
  $headers = [
    'Authorization: bearer ' . $token,
    'Accept: application/vnd.github.v3+json',
    'User-Agent: after_saving_wordpress'
  ];
  $data = [
    'event_type' => 'after_saving_wordpress',
  ];

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  curl_setopt($ch, CURLOPT_HEADER, true);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_exec($ch);
  curl_close($ch);
}

上記を追加すると、「投稿」の記事が対象になり、記事のステータスが変わるたびに実行されるようになります。

今回は、
「下書き」→「公開」
「公開」→「下書き」
「公開」→「ゴミ箱にいれる」
の3条件で動作するようにしてあります。

アクションフックについて詳しく知りたい方は、こちらを御覧ください!→https://wpdocs.osdn.jp/投稿ステータスの遷移

ちなみに、カスタム投稿タイプで利用したい場合は下記になります。

ここでは「news」としています。


/* -------------------------- */
/* GitHub ActionsへのHookを設定 */
/* -------------------------- */
add_action('publish_news', 'after_saving_wordpress', 10, 2); // ←publish_newsに変更
add_action('publish_to_draft', 'publish_to_saving_wordpress', 10, 1);
add_action('publish_to_trash', 'publish_to_saving_wordpress', 10, 1);

function after_saving_wordpress($post_id, $post) {
  dispatch_github_actions();
  return true;
}

function publish_to_saving_wordpress($post) {
  if ($post->post_type === 'news') { // ←newsに変更
    dispatch_github_actions();
    return true;
  }
  return false;
}

これでWordPressの記事を保存したタイミングで条件にあえば自動で実行できるようになりました!

ただ個人的には、記事保存のタイミングで毎回ビルドを走らせたくなかったので、管理画面上でボタンを押したタイミングで実行されるようにしました。

以下コードを、functions.phpの一番下に追加してください。


/* -------------------------- */
/* GitHub ActionsへのHook実行を管理画面に追加 */
/* -------------------------- */
add_action('admin_menu', 'custom_menu_page');
function custom_menu_page() {
  add_menu_page(
    'GitHub Actionsフック実行',
    'GitHub Actionsフック実行',
    'manage_options', // WPのアカウント権限を変えたい場合はここを変更する
    'custom_menu_page',
    'add_custom_menu_page',
    'dashicons-admin-generic',
    100
  );
}
function add_custom_menu_page() {
  if ( !current_user_can( 'manage_options' ) ) { // WPのアカウント権限を変えたい場合はここを変更する
    wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
  }

  echo '<div class="wrap">';
  echo '<h2>GitHub Actionsフック実行画面</h2>';

  if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty( $_POST['run'] ) && $_POST['run'] === 'run') {
    dispatch_github_actions();
    echo "GitHub Actionsのフックが実行されました。";
  } else {
    echo '<form method="post" action="">';
    echo '<button type="submit" name="run" value="run">実行を開始</button>';
    echo '</form>';
  }
  echo '</div>';
}

上記を追加すると、WordPressの管理画面の左メニューに「GitHub Actionsフック実行」追加されます。

アクセスすると、「実行を開始」ボタンが出てくるので、クリックするとGitHub Actionsを実行できるようになります!

これで無事ビルドされてレンタルサーバーにアップロードされるようになりました。

まとめ

Nuxtを使いたいけど、SSR用サーバーがコスト的にも難しい、でもコンテンツ管理はWordPressでしたいという声をちらほら聞くことがあるので、この方法を使えばいい具合に実現できると思います。

Nuxtでフロントページを作るのでサーバーサイドでのセキュリティの不安がなくなったりとメリットも充分得られる構成だと思うので一度試してみるといいかと思います。

記事数や更新頻度が多かったりすると、相対的にビルドに時間がかかるようになるので、ご注意ください!

About Me

プロフィール画像

ユーキと申します。北海道恵庭市という札幌と新千歳空港の間でフリーランスのWebエンジニアとして活動してます。

当サイトのブログでは、主にWeb制作全般、フリーランス周りの情報など色々なノウハウや知識を載せています。
その他日々気になったこと、思ったことも書いてます。

お仕事の相談など何かありましたら、お問い合わせかツイッターのDMからお気軽にご連絡くださいませ。

お問い合わせはこちら

ツイッターはこちら

ポートフォリオはこちら

Latest Posts

Popular Posts

TOP