👀

Jamstack な Nuxt.js + microCMS サイトにプレビューページを追加してみた

2023/03/13に公開

ハコベルシステム開発部のおおいし (@bicstone) です。普段はフロントエンドエンジニアとして物流DX SaaSプロダクトの開発を行なっています。

この記事では、 Nuxt.js (static mode) + microCMSで構成したJamstackなサイトにおいて、デプロイ不要でコンテンツをプレビューするページを追加し、執筆者が下書きを即時プレビューできるようにする方法を解説します。

(Vue.js 2, Nuxt.js 2を使用しています)

ハコベルサービスサイトの技術構成について

ハコベルのサービスサイトは、Nuxt.jsのstatic modeと、ヘッドレスCMSであるmicroCMSを活用したJamstack構成で作られています。

https://nuxtjs.org/ja/docs/concepts/static-site-generation/

デプロイ環境において、microCMSのAPIを呼び出してコンテンツを埋め込んだ静的なHTMLとJavaScriptを生成します。これらの静的ファイルをCDNに保存し、CDNからユーザーに配信するというアーキテクチャとなっています。

クライアントサイドのアクセスに対し、静的ファイルをCDNから配信するだけで完結します。パフォーマンスの高さや、セキュリティリスクを軽減できる利点があります。

また、静的ファイルにすでにコンテンツが埋め込まれているため、クライアントサイドからmicroCMSのAPIを呼び出す必要がなくなります。

課題

このアーキテクチャでは、microCMSで管理しているコンテンツの変更がある度にデプロイを行わなければ、クライアントサイドで最新のコンテンツを反映できません。

ハコベルでは、本番環境に新しいコンテンツを反映する前に検証環境へデプロイし、検証環境で関係者が確認後に本番環境へデプロイするというフローを踏んでいます。

しかし、組織の拡大に伴い、お知らせやセミナー情報などコンテンツの更新頻度が増加しています。デプロイするまで検証環境でプレビューを表示できないことは、運用において大きな課題になっていました。

Nuxt.js の Preview Mode について

このような課題に対して、 Nuxt.jsではPreview Modeという機能が用意されています。 microCMSでも紹介されています。

https://nuxtjs.org/ja/docs/features/live-preview/

https://blog.microcms.io/nuxt-preview-mode/

ユーザーから特定のクエリが渡された場合、クライアントサイドで新たにコンテンツを再取得するという手法です。

しかし、この手法では新たなコンテンツを作成しても、ルーティングが生成されておらずページが存在しないので404エラーになるという課題があります。

そのため、CDN側でルーティングを構成する必要があります。将来的なインフラの移行を予定しており、移動コスト軽減の観点から、この手法は採用できませんでした。

動的にコンテンツを表示するプレビュー専用ページを作成

そこで、私たちはURLクエリからcontent IDを取得し、クライアントサイドでコンテンツを取得するプレビュー専用ページを作成することにしました。

mountedを使用した単純なVueファイルです。 asyncDataを使用してしまうと、 静的ファイル生成時にコンテンツを取得しようとして404エラーが発生し失敗してしまいます。

/pages/preview/news.vue
<template>
  <NewsPage v-if="content" :content="content" />
</template>

<script lang="ts">
  import Vue from "vue";
  export default Vue.extend({
    components: { NewsPage },
    data() {
      return {
        content: null as NewsContent | null,
      };
    },
    async mounted() {
      const { id } = this.$route.query;
      const content = await this.$news.get(id);
      this.content = content;
    },
  });
</script>

このページにアクセスされたら、クライアントサイドで毎回mountedが呼び出されます。 URLクエリのcontent IDをmicroCMSのプラグインに渡すことで最新のコンテンツが取得されます。

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

プレビューができるページを作成できました。しかし、このファイルを本番環境に公開することは、次の理由から避ける必要があります。

  • microCMSのアクセストークンが露出する
  • 下書きのコンテンツが漏洩する
  • プレビューページが検索エンジンのクローラーにインデックス付けされてしまう

そのため、本番環境ではページを生成しないように制御します。

/nuxt.config.js
const {
  CMS_BASE_URL,
  CMS_API_KEY,
  ENVIRONMENT,
} = process.env

export default {
  target: 'static',  // static モード

  // 検証環境のみ、下書きにアクセス可能な microCMS アクセストークンを
  // クライアントサイドに出荷する
  publicRuntimeConfig: ENVIRONMENT === "development"
  ? {
      CMS_BASE_URL,
      CMS_API_KEY,
    }
  : {},

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

microCMS の設定

最後に、コンテンツの執筆者がより容易にプレビューページを開けるよう、microCMS管理画面の設定を変更します。

「API設定」→「画面プレビュー」から遷移先URLを設定します。

microCMS のスクリーンショット。「API 設定」、「画面プレビュー」の「遷移先 URL」に「https://example.com/preview/news?id={CONTENT_ID}」を設定し、「画面プレビューボタンの表示」を活性にしている

執筆画面に「画面プレビュー」ボタンが追加されました。このボタンをクリックすると、即時にプレビューページが開きます。

microCMS のスクリーンショット。「お知らせ」の記事を編集する画面に「画面プレビュー」というボタンが表示されている

この検証環境でのプレビューページは、社内環境であればURLからアクセスが可能なので、デプロイせずとも関係者がサイト上の表示を確認することが可能になりました。

microCMS のスクリーンショット。先程編集した記事の内容で、ハコベルのサービスサイトサイト上に「お知らせ」が表示されている

まとめ

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

Hacobell Developers Blog

Discussion