Nuxt (static mode) + microCMS ブログにプレビューページを追加した話

目次

はじめに

Nuxt (static mode) + microCMS ブログに、nuxt のプレビューモードを使用せずにプレビューページを追加してみました。デプロイ不要で内容を0秒でプレビューする方法を解説します。
(vue 2, nuxt 2 を使用しています)

背景

nuxt.js (static mode) + microCMS で構成されてるブログがあります(当サイトではありません)。
microCMS で記事を書いたあと、 nuxt.js タスクランナーの generate コマンドを実行します。タスクランナーは microCMS の REST API から記事データを取得して静的な HTML に書き出します。その 静的 HTML を S3 などにデプロイすることで公開します。
この方法は SSG (Jamstack) と呼ばれます。閲覧する側から見ると完全に静的な HTML なので圧倒的なパフォーマンスの高さや、セキュリティの懸念が少ない利点があります。一方、 nuxt.js の generate タスクランナーを実行しなければ最新の記事情報を表示することができません。
WordPress のように即時プレビューを表示することが不可であることは、運用において大きな課題になりました。

nuxt.js の プレビューモード について

このような課題に対して、 Nuxt.js では プレビューモード という機能が用意されています。 microCMS でも推奨されています。
Nuxt - プレビューモード
https://nuxtjs.org/ja/docs/features/live-preview/
Preview Modeを使ってコンテンツの下書きプレビューを行う | microCMSブログ
https://blog.microcms.io/nuxt-preview-mode/
生成された静的 HTML の中に特定のクエリが渡された場合、新たにデータを再取得するという手法です。
一見この方法で解決しそうですが、新たな記事を作成する場合に、そのままではページが存在しないので 404 エラーになるという課題があります。ホスティング側でルート設定などをすることも可能ではありますが、ホスティングの設定が増え、 Jamstack のシンプルな利点が損なわれてしまいます。

プレビュー用のページを作成

そこで、クエリから ID を取得し、クライアントサイドでデータを取得することができるプレビュー用のページを作成してみました。
mounted のみを使用した単純な Vue ファイルです。 asyncData を使用してしまうと generate 時に nuxt.js がデータを取得しようとして 404 エラーが発生してしまいます。
<template>
  <BlogContent v-if="content" :content="content" />
</template>

<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
  components: { BlogContent },
  data() {
    return {
      content: null as BlogContent | null,
    }
  },
  async mounted() {
    const { id } = this.$route.query
    const content = await this.$microcms.get({...})
    this.content = content
  },
})
</script>
このページにアクセスされたら、クライアントサイドからのアクセス時に毎回 mounted が呼び出されます。クエリの id を取得して microCMS のプラグインを呼び出し読み込んでくれます。

本番環境でアクセスできないようにする

プレビューができるページを作成できました。しかし、このファイルを本番環境に公開することは避ける必要があります。
  • MicroCMS のアクセストークンが漏洩する
  • 下書きのコンテンツが漏洩する
  • プレビューページが検索エンジンのクローラーにインデックス付けされてしまう
そのため、本番環境ではページを生成しないように制御します。
nuxt.config.js
const enablePreviewMode = false // プレビューモードを環境変数などで制御

export default {
  target: 'static',  // static モード
  // プレビューモードが有効な場合のみアクセストークンをクライアントサイドに出荷する
  publicRuntimeConfig: enablePreviewMode ? publicRuntimeConfig : {},

  generate: {
    // プレビューモードが無効な場合にプレビューページを作らない
    exclude: enablePreviewMode ? [] : [/^\/preview/],
  },
}

まとめ

プレビューモードのページを作ることで、Jamstack を維持したまま運用の負荷を大きく下げることができました。

シェア

Twitter
Facebook
はてブ
LinkedIn
LINE
Pocket