1
/
5

【開発日誌 #7】WordPress × Nuxt.js でヘッドレスCMSを構築

WordPressを提案する過程で課題になることの多い

「セキュリティの担保」と「表示速度向上」の対策として、

「WordPressのヘッドレスCMS化」をクライアントに提案したところ採用となりました。

開発におけるポイントに絞って紹介いたします。


【要件】

・会員制サイト

・サイト運用側でWordPressの管理画面を使用してコンテンツ登録・配信、会員管理をしたい

【課題】

・管理画面の使いやすさや、カスタマイズ性を考慮してWordPressを採用したいが、

WordPressのセキュリティ面がクライアントの社内レギュレーション上NG

・WordPressはページアクセスのたびに動的にページを生成するため、表示速度に難があり、サイトの作りによっては非常に重くなる


ヘッドレスCMSとは?

「ユーザがアクセスする画面を持たないCMS」のことです。

今回、WordPressはCMS機能だけ使用して、WordPressの標準機能REST APIにより画面表示側のNuxt.jsへAPI通信によりJSON形式でコンテンツを配信しています。

ヘッドレスCMS自体の解説は下記が詳しいです。

https://blog.microcms.io/what-is-headlesscms/

ヘッドレスCMSが近年選定される理由については、下記が詳しいです。

https://blog.microcms.io/7reasons-to-choose-headlesscms/

2つ目の解説の中で、選定理由の1つとして挙げられている「セキュリティの担保」が、本案件のヘッドレスCMS採用理由でした。

以下、「セキュリティの担保」説明部分の引用となります。

===

従来のCMSの代表格ともいえるWordPressは膨大な実績がある一方、攻撃対象としても狙われやすいことも事実です。

脆弱性データベースには2000件以上の脆弱性が報告されています。

従来のCMSの場合、こういった脆弱性が特に大きな問題となりやすいのには理由があります。

それは表示面、データベース、管理画面といったサイトを表示するのに必要なシステム構成を全てカバーしているためです。

攻撃者から見ると一つでも攻撃の糸口を見つけられれば大きな影響をあたえられる可能性が出てきます。

一方でヘッドレスCMSを使った場合はどうなるでしょうか?

この場合、(きちんと設計が行われていれば)外部に公開されているのは表示面だけになります。

そのため攻撃者から見たときに内部的な構造がわからず、攻撃の糸口を見つけられる可能性は大きく下がるでしょう。

===


表示速度についてはステージング環境移行後に確認・対応する方針で開発着手しました。

【構成】

〈WEBサーバー〉

画面表示側のNuxt.jsを設置します。

APPサーバー上に設置したWordPressからREST API経由でコンテンツ情報を取得して、Nuxt.js側に動的出力します。

Nuxt.jsのビルド選択肢にはSPA・SSR・SSGがありますが、以下の流れでSPAを採用しました。

・会員サイトのため、ログイン機能あり→SSGは不向き

・会員サイトのためSEO対策は不要、またNuxt.jsは最終的に既存サーバの下層ページに設置予定→Node.jsが必要なSSRにする必要なし→SPAに決定

WordPress管理画面更新後はNuxt.jsの画面をリロードすればREST APIからコンテンツを再取得するので、Nuxt.jsのソースを変更しない限りリビルドは必要ありません。

〈APPサーバー〉

ヘッドレスCMSに該当するWordPressはこちらに設置します。

WordPressのDBは同じサーバ内に設置しました。

WordPressをヘッドレスCMS化するには、テーマファイル構成を必要最小限にします。

header.php、footer.phpなどの画面表示用テンプレートは使用しないため削除し、

・functions.php(管理画面やカスタム投稿の設定、カスタムAPI追加実装など)

・index.php(0byte)

・style.css(テーマのメタデータコメントのみ)

・screenshot.png(管理画面のテーマ一覧で見えるサムネイル画像)

のみとしています。


【開発のポイント】

1.セキュリティ対策

運用時の配慮として、WordPressが外部から攻撃されないように隠します。

WordPressのセキュリティ対策として

・管理画面へIP制限をかける

・管理画面のログインURL変更

ヘッドレスCMS化に伴うセキュリティ対策として

・Nuxt.js側で表示する画像などのメディアファイルが、WordPressを設置しているAPPサーバのドメインが含まれるURLで渡されてしまう。メディア配信用のサーバやサブドメインを別に用意するなどしてAPPサーバを隠す。

・会員登録申請の承認時などにユーザに送信されるメール本文にWordPressサイトのURLが含まれないように設定。

以上を対応します。


2.Nuxt.js + WP REST APIでの開発

やりたいことはコンテンツ登録・配信、会員管理ですが、コンテンツ登録・配信に絞って解説します。

先にHTML+CSSでの静的ページ構築と、WordPress管理画面でコンテンツ登録し易いよう作り込みをある程度進めてから、Nuxt.js+REST APIへ移行しました。

・サイト共通で使用するヘッダー、フッターはcomponents、404はlayoutsへ移行

・APIで受信したコンテンツを、動的出力するようhtmlからNuxt.js/Vueへ書き換え

・API通信はJavaScriptライブラリAxiosを導入

・管理画面でACFを使用しているので、プラグインACF to REST APIも導入しカスタムフィールドの値を出力

例として、製品情報一覧ページ(pages/product/index.vue)のソースを紹介します。

async asyncData({ $axios }) {...}でカスタム投稿 製品情報(product)のデータを取得します。

取得したデータはdataプロパティなのでそのままtemplateタグで使用することができます。

Nuxt.jsにおけるaxios, asyncDataの使い方はこちらが参考になります。

https://reffect.co.jp/vue/nuxt-js-axios-asyncdata


<script>
export default {
 head() {
   return {
     // 省略
   }
 },
 async asyncData({ $axios }) {
   const product_params = "?per_page=100&status=publish&orderby=menu_order&order=asc"; // パラメーター
   const product_url = "/wp/v2/product" + product_params; // 取得先のURL(wp product)
   const product_response = await $axios.$get(product_url); // リクエスト(Get)
 
   return {
     product_posts: product_response, // 配列で返ってくるのでJSONにして返却
   };
 },
}
</script>


次はtemplateタグ内の記述です。

例としてサイドバーの箇所のみピックアップしています。

asyncDataで取得したproduct_postsを元にv-forを使用してサイドバーを生成しています。製品情報は各製品の詳細ページが存在し、product_post.idは詳細ページのスラッグの値が入っています。

<ul class="sideBar_list">
    <li v-for="(product_post, index) in product_posts" :key="index" v-if="product_post.acf.productPost_title_for_archivePage && (product_post.acf.productPost_thumb_pc || product_post.acf.productPost_thumb_sp)" class="sideBar_listItem">
        <nuxt-link class="sideBar_listItemLink" :to="'/product/' + product_post.id">
           <p class="sideBar_listItemLinkTxt" v-html="product_post.acf.productPost_title"></p>
        </nuxt-link>
    </li>
</ul>


3.表示速度の向上

開発がある程度進んだ段階で、ステージングサーバへ移行し表示確認したところ、画面遷移時の表示速度に難がありました。

ブラウザ検証ツールのNetworkから確認すると、API通信を毎回読み込む挙動が見られました。

以下のキャッシュ設定により初回読み込み以外の表示速度は改善しました。

・Nuxt.jsが載っているWEBサーバ側でAxiosの拡張機能リクエストキャッシュを設定

・WordPressが載っているAPPサーバ側でOPchacheを設定


WEBサーバ側の対応内容詳細

・Nuxt.jsが載っているWEBサーバ側でAxiosの拡張機能リクエストキャッシュを設定

こちらの記事を参考にしました。

https://dev.classmethod.jp/articles/nuxtjs-axios-cache/

他には以下を対応しています。

・Nuxt.js側のコンソールエラーを開発段階で全て解消

・画像コンテンツがあるため、lazyloadを採用


APPサーバ側の対応内容詳細

・以前からある方法ですが、サーバへOPcacheを設定追加したところ、表示速度が劇的に改善しました。

OPcacheについての解説

https://weblabo.oscasierra.net/php-opcache/

PHPモジュールモードとCGIモード

https://www.fenet.jp/dotnet/column/tool/9374/

過去のWordPress構築案件で画面表示速度改善のため対応した実績はありましたが、REST API通信にも有効でした。尚、DBの速度については問題ないことを確認しています。

【まとめ】

「WordPressのヘッドレスCMS化」と、「セキュリティの担保」と「表示速度向上」のための対応内容をざっくり解説させていただきました。

各クライアントから求められるセキュリティ要件も年々厳しくなってきています。

ヘッドレスCMSは様々な製品がございますが、知名度や管理画面のカスタマイズ性からWordPressを選択したい、という要望と厳しいセキュリティ要件を両立するために、提案の選択肢として、WordPressのヘッドレスCMS化は有効だと思います。


WordPressをヘッドレスCMS化したメモ
年単位でブログを放置しておきながら何事もなかったかのように再開。今回の記事ではWordpressの制作について書きなぐります。わりとありきたりな内容です。 今となってはヘッドレスCMSとしてしか使いた
https://trs.mn/blog/2020/02/09/wordpress/
株式会社コムデ's job postings
8 Likes
8 Likes

Weekly ranking

Show other rankings
Invitation from 株式会社コムデ
If this story triggered your interest, have a chat with the team?