WordPressサイトをWP REST API + Nuxt.jsでリニューアルした際のポイントまとめ

先日Glatchのポートフォリオサイトをリニューアルしました。
前回の記事では妻がポートフォリオの設計・デザインプロセスに関して投稿してくれました。

今回は実装編です。
普段は技術系の記事はテックブログに書いているのですが、ポートフォリオの宣伝も兼ねているので今回はこちらに投稿します。良かったらテックブログも見ていただけると嬉しいです。

さて技術面に関してはせっかくリニューアルするのでこの機会に新しい技術を試したい、でもWordPressで管理してきた資産はできればそのまま活かしたい、という2つの要望が自分の中にありました。

この2つを両立させるためにコンテンツ管理には引き続きWordPressを使用し、フロント部分にモダンなフレームワークを採用することで要望を満たしました。
検討の結果WP REST API + Nuxt.jsというJAMstackな構成で構築することにしました。

本記事ではWordPress製のサイトをWP REST API + Nuxt.jsの構成に移行するにあたって、個人的に参考にさせていただいた記事やハマりどころだったポイントをまとめました。同じ構成でサイト作成を考えている方の参考になれば幸いです。

Nuxt.jsを採用した理由

開発のポイントを紹介する前に、なぜNuxt.jsを採用したのかについて書いてみます。
いわゆる通常のWebサイトの制作スキルは、モダンな環境でWebサービスをバリバリ開発している方からすれば、レガシーな技術も未だに現役であると言えるのではないでしょうか?

もちろん必ずしもレガシーなものが悪いわけではなく、枯れた技術は安心して使える場合も多いですし、案件によって対応環境に幅がある受託制作においては、効率的に制作するうえでもとても重宝しています(さすがに使用頻度は減ってきましたがjQuery大好きです)。

しかしイチ開発者からすれば、モダンな技術に触れたいという欲求や、取り残されていく不安も少なからずありますので、クライアントの要件やサイトのパフォーマンスを損なうことなく新しい技術を取り入れられないだろうかと日々虎視眈々と機会を伺っているのもまた事実です。

またWebサイト制作にJavaScript製フレームワークの採用を検討する際にどうしても避けて通れないのはSEOです。Googleに関しては問題ないのですが、TwitterやFacebookなどのOGP関連には不安が残ります。

そこで候補に上がったのが静的に生成が可能なJavaScriptフレームワークです。幣テックブログではGatsbyというReact製の静的サイトジェネレーターを使用しているのですが、Vueにもしっかり触れておきたかったため、今回はVue製のフレームワークに絞って調査し、中でも採用実績も多く開発も活発なNuxt.jsを採用することにしました。

Nuxt.jsを採用した結果

WordPressと組み合わせることで双方の良いとこ取りができた

先述の通り、WordPressで管理したままフロントにNuxt.jsを採用したことで、コンテンツ運用の体験はそのままに管理しやすいフロントエンドを実現できました。

開発が楽しくなった

個人的にはとても重要な要素です。自身のモチベーションを理由に技術選定できるのは自案件の良いところですね。

各要件・機能のポイント

前置きが長くなりましたが、本題に入ります。
WP REST API + Nuxt.jsの構成で構築する中で、使用した技術やハマった箇所を備忘録的にご紹介します。

お問い合わせフォーム

WordPressではContact Form 7という定番のプラグインを使用していました。

なんとContact Form 7はNuxt.jsでも使用できます。
axiosを使用してWP REST API経由でフォームに入力されたデータを送ることで動作するのです。

基本的には以下の記事を参考に実装を進め、問題なく動作しました。

【Nuxt.js】お問い合わせフォーム実装にWordPressのContact Form 7で対応する

フォームのバリデート

フォームのバリデートにはvuelidateという便利なライブラリーがあったので使用しました。
Vue.jsの公式サイトでも紹介されていて、GitHubのスターも多く開発も活発なので安心して導入できました。

「もっと見る」ボタン

ブログページで使用している「もっと見る」ボタンはvue-infinite-loadingというプラグインを使用して実装しました。このプラグインのベーシックな使い方だとvue-infinite-loadingを組み込んだ位置までスクロールすると、自動的に記事を取得するというプラグイン名の通り、無限スクロールの仕様になっています。しかし今回はボタンをクリックすると続きの記事を取得するようカスタマイズして使用しました。

シンタックスハイライト

ブログにコードを記載する場合の見栄えを良くするシンタックスハイライトは、vue-prismというVue.jsにPrism.jsを導入できるプラグインがあるのでこちらを使用すれば簡単でした。

ページ遷移時のtransition

Nuxt.jsにはtransitionプロパティというのが標準で備わっていて、こちらを使用して簡単にページ間の移動にtransition効果をつけることができます。

API: ページ transition プロパティ – NuxtJS

head内タグ

head内タグの設定はheadメソッドを使用して設定が可能です。
基本的に対象のpages配下のvueファイルに設定しています。
ブログ記事と制作実績の各ページの動的ルーティングページでは、metaタグやogpタグが変わり、記事毎にユニークな値を設定する必要があるため、SEOで定番のWordPressプラグインであるAll In One SEOを使用し、All In One SEOで設定した各値をWP REST APIに追加して使用しました。

WordPressのREST APIにAll in One SEOの項目を追加する方法

Google Analytics

公式ドキュメントにも「Google アナリティクスを使うには?」というページがありますが、今回はgtag.jsを使用したかったのでgtag.jsの導入方法を解説した下記の記事を参考にしました。

NuxtでGoogleアナリティクス(gtag.js)を実装する

Google Adsense

Nuxt CommunityにGoogle Adsenseを導入する為のモジュールであるnuxt-community/google-adsense-module: Google AdSense module for Nuxt.jsがあるのでそちらを使用しました。

共通のSassの読み込み

Nuxt.jsで各コンポーネントで共通で使用したいSassの変数などは、個別で読み込むのは手間なので、Nuxt Style Resourcesというモジュールを使用しました。

《Nuxt.js》Sassの共通の変数やmixinを一括で各コンポーネントに読み込む方法

構造化データマークアップ

構造化データマークアップにはnuxt-jsonldというプラグインを利用しました。

ハマりどころと解決法

src属性以外の相対パス指定が解決されない

以下の記事のとおり、Nuxt.jsはデフォルトでsrc属性のみ相対パスの解決を行うため、nuxt.config.jsに設定を追加する必要があります。

ハマりメモ:bootstap-vueでb-imgのsrc属性に相対パスが指定出来ない。

JavaScriptでwindowが取得できない

これはNuxt.jsがSSRのため、普通にwindowやdocumentを使用しようとするとエラーになります。
公式ドキュメントにあるようにprocess.client変数で条件分岐させることで実行可能になります。

if (process.client) {
// ここに処理
}

window または document が undefined

generateしたファイルに動的ルーティングページが含まれていない

今回はgenerateコマンドを使用して静的ファイルを生成してサーバーにアップすることにしました。
静的ファイルの生成にはnuxt generateコマンドで行うのですが、デフォルト設定のままだと動的なルーティングは無視されます。

今回の場合、ブログの投稿記事と制作実績の各実績ページがそれにあたります。ここはnuxt.config.jsgenerateAPIにroutesというプロパティがあるので、そこで動的ルーティングが生成されるよう設定を行います。

generate: {
  routes () {
    return Promise.all([
      axios.get('https://sample.com/wp-json/wp/v2/posts?per_page=100'),
      axios.get('https://sample.com/wp-json/wp/v2/works?per_page=100')
    ])
    .then((res) => {
      const posts = res[0]
      const works = res[1]
      return posts.data.map((post) => {
        return {
          route: '/blog/' + post.slug,
          payload: post
        }
      }).concat(works.data.map((work) => {
        return {
          route: '/works/' + work.slug,
          payload: work
        }
      }))
    })
  }
}

generateしたファイルに404ページが含まれていない

エラーページは公式ドキュメントにも書いてある通りlayoutsディレクトリにlayouts/error.vueファイルを追加することで作成できます。

ビュー – NuxtJS

しかしnpm run generateをしてもデフォルトでは200.htmlとして生成され、404.htmlは生成されません。200.htmlでも中身は作成したerror.vueなので構わないのですが、何だか気持ち悪いので404.htmlとして生成したいところです。その場合はnuxt.config.jsgeneratefallbackを追記することで実現できます。

generate: {
  fallback: true
}

今後の課題

プレビュー画面をどうするか

WordPressをHeadlessにした代償として記事執筆時のプレビュー画面を失いました。
Gutenbergをサイトデザインに合わせるか、下記の方法でもイケるのかなと思っています。

WordPress x Vue.jsで公開済み記事の編集時プレビューを表示する(SPA実装)

おわりに

WP REST API + Nuxt.jsの構成の情報は思っていたよりも少なかったので、この記事が同じ構成で構築をしている開発者の工数削減に少しでもなれば良いなあと思っています。

私たちGlatchはコーポレートサイト制作を得意とするWeb制作事務所です。
お気軽にご相談・お問い合わせください。