microCMS

microCMSとNuxtでプレビュー画面を作成する

チュートリアル
2020/09/10 柴田 和祈

こんにちは、柴田です。
Jamstack構成においてはプレビュー画面の表示が一つの躓きポイントだと思います。
プレビュー画面を表示する方法はいくつかありますが、今回は/draftというプレビュー用のURLを用意する方法をご紹介します。

こちらの記事のコードに機能を追加していきたいと思います。

microCMS + NuxtでJamstackブログを作ってみよう
https://microcms.io/blog/microcms-nuxt-jamstack-blog


前提

プレビュー画面とは下書き状態のコンテンツを閲覧する画面です。
microCMSではコンテンツが「下書き中」ステータスの場合、draftKeyが発行されます。

コンテンツ取得のAPIリクエスト時にクエリパラメータとしてdraftKeyを与えることで下書き中のコンテンツを取得することができます。
また、microCMSにはプレビュー機能があります。
API設定 > 画面プレビューで、「画面プレビュー」ボタンをクリックした際の遷移先URLを指定することができます。

遷移先URLには記事のcontentIddraftKeyを動的に埋め込むことが可能です。
この仕組みを利用し、フロントエンド側でURLからcontentIddraftKeyを受け取り、microCMSに対してAPIリクエストを行うことで下書き中のコンテンツを取得し、プレビュー画面を表示します。

実装方法

まずはプレビュー用のルーティング(/draft)を用意します。
/pages配下にdraft.vueを作成しましょう。

プレビューページにおいては、ビルド時ではなくURLからアクセスされたタイミングでクライアントサイドからAPIリクエストを行います。
よって、asyncDataメソッドではなくcreatedメソッドを用います。

// pages/draft.vue

<template>
  <main v-if="data" class="main">
    <h1 class="title">{{ data.title }}</h1>
    <p class="publishedAt">{{ data.publishedAt }}</p>
    <div class="post" v-html="data.body"></div>
  </main>
</template>

<script>
import axios from 'axios'

export default {
  data() {
    return {
      data: {}
    };
  },
  async created() {
    const query = this.$route.query;
    if (query.id === undefined || query.draftKey === undefined) {
      return;
    }
    const { data } = await axios.get(
      `https://your-service-id.microcms.io/api/v1/blog/${query.id}?draftKey=${query.draftKey}`,
      {
        headers: { 'X-API-KEY': 'your-api-key' }
      }
    )
    this.data = data;
  },
}
</script>

処理の流れとしては以下のようになります。

1. URLから/draft?id=XXXXXXXX&draftKey=YYYYYYYYのようにアクセスする
2. this.$route.queryからiddraftKeyを受け取る
3. microCMSに対してiddraftKeyを用いてAPIリクエストを行う
4. 取得データをテンプレート側に渡して描画する

microCMSの設定

Nuxt側の準備はできたので、次にmicroCMS側の設定を行います。
API設定 > 画面プレビュー で以下のようにURLを設定しましょう。

https://your-service-name.netlify.app/draft/?id={CONTENT_ID}&draftKey={DRAFT_KEY}

これでmicroCMS側の設定も完了です。
コンテンツ編集画面で「画面プレビュー」ボタンをクリックすればプレビューを表示できるようになります。

API-KEYを隠す方法

プレビュー時はクライアントサイドからAPIリクエストを行うため、API-KEYが見えてしまいます。
(※要件によっては特に見えていても問題ないとは思います)

これを隠したい場合は、サーバサイドで一度処理を挟む必要があります。
一例として、Netlify Functionsを利用する方法を紹介します。

Netlify Functionsとは

Netlifyが提供するFaaS(Function as a Service)です。
Functionをクラウド上で実行することができる優れものです。

今回はこちらを利用することで、サーバーレスでサーバーサイドの処理を行なっていきます。
(せっかくJamstackなので、ここでサーバーを建ててしまっては本末転倒です)

環境準備

まずはnetlify-lambdaというパッケージをインストールしましょう。

$ npm install -D netlify-lambda


次に、npmスクリプトで呼び出せるようにpackage.jsonに設定を追記します。

// package.json

//"scripts": {
  "function:build": "netlify-lambda build functions/",
  "function:serve": "netlify-lambda serve functions/"
}
//


また、最終的にFunctionのデプロイ先をnetlify.tomlにて設定します。

// netlify.toml

[build]
  functions = "dist/api"


下書き取得用のFunctionを実装

Netlify Functionsはfunctions/配下のソースコードに対して動作します。
今回はfunctions/draft.jsを作成します。

// functions/draft.js

const axios = require('axios');

exports.handler = async (event) => {
  const { id, draftKey } = event.queryStringParameters;
  if (!id) {
    return {
      statusCode: 400,
      body: JSON.stringify({
        error: 'Missing "id" query parameter',
      }),
    };
  }
  return axios
    .get(
      `https://your-service-id.microcms.io/api/v1/blog/${id}?draftKey=${draftKey}`,
      {
        headers: { 'X-API-KEY': 'your-api-key' },
      }
    )
    .then(({ data }) => ({
      statusCode: 200,
      body: JSON.stringify(data),
    }))
    .catch((error) => {
      return {
        statusCode: error.response.status,
        body: JSON.stringify(error.response.data),
      }
    });
};


クライアントから渡されるiddraftKeyのほかに、サーバサイドでX-API-KEYを付加してmicroCMSにAPIリクエストを行います。

この状態でnpm run functions:serveを実行するとローカル環境(9000番port)でサーバーが起動するので、ブラウザから下記のようにアクセスするとレスポンスとして返却されたJSONが表示されます。

http://localhost:9000/.netlify/functions/draft/?id={記事のcontentID}&draftKey={記事のdraftKey}

次に、フロントからこのNetlify Functionsを呼び出すために、pages/draft.vueを修正します。

// pages/draft.vue
  
async created() {
  const query = this.$route.query;
  if (query.id === undefined || query.draftKey === undefined) {
    return;
  }
  const { data } = await axios.get(
    `/.netlify/functions/draft?id=${query.id}&draftKey=${query.draftKey}`,
  );
  this.data = data;
},


Netlifyにデプロイすると、サイトと同じドメインで通信を行うことができるため、上記のように記述することができます。
また、Netlify Functionsへのリクエストなので、ここでAPI-KEYは不要になります。

一方で、開発時(npm run dev時)はnpm run functions:serveによって起動したlocalhost:9000に対して通信を行いたいですよね。

そこで、Nuxt Proxyを用いて、開発時のみlocalhost:9000に向き先を変更します。

$ npm i -S @nuxtjs/proxy


nuxt.config.jsにproxyの設定を追加します。

// nuxt.config.js

{
  // 略
  modules: [
    '@nuxtjs/proxy'
  ],
  proxy: {
    '/.netlify': 'http://localhost:9000'
  },
  // 略
}


以上の設定により、開発時はローカルに起動したNetlify Functions経由で下書きが取得できるようになりました。

※ただし、proxyはgenerated/staticモードでは動作しないようです。
npm run generage && npm start時にも動作確認をしたい場合は別の方法を考える必要があります。

デプロイ

最後にNetlifyへのデプロイです。
Jamstackによる静的ファイルのデプロイとNetlify Functionsのデプロイが必要なので、Netlifyには次のようにビルドコマンドを設定します。

以降のデプロイからはFunctionsもデプロイされるようになります。

以上で下書きプレビュー時にもAPI-KEYを隠すという作業は完了です。

おわりに

Nuxt × microCMSのJamstack構成におけるプレビューの実装方法について解説しました。
ヘッドレスCMSの場合でも自前で実装すれば、一般的なCMSのようにプレビュー環境を構築することが可能です。

今回ご紹介したのは一例で、他にもプレビュー用に別環境を建てたり、Nuxt Preview Modeの機能を使ったりする方法もあります。
みなさんも良い実装方法をご存知でしたらブログ等でぜひ発信してみてください。

-----

microCMSは日々改善を進めています。
ご意見・ご要望は管理画面右下のチャット、公式Twitterメールからお気軽にご連絡ください!
引き続きmicroCMSをよろしくお願いいたします!

ABOUT ME

柴田 和祈
microCMSのデザイン、フロントエンド担当 / ex Yahoo / 2児の父 / 著書「React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで 」 / Jamstack

microCMSとは

  1. 開発者、編集者どちらも分かりやすい管理画面

  2. 細かな権限管理や豊富な外部サービス・データ連携

  3. 安心の日本製・日本語でのチャットサポート