MovableType + Nuxt.jsでJamstackなサイトを作る

Posted on:2020-12-14

この記事は Jamstack Advent Calendar 2020 の14日目の記事です。

Jamstackに関する記事がたくさん出て、色々とやってはいたものの二番煎じみたいな感じになるのであまり情報出てないMovableTypeでやるJamstackのテンプレートをNuxt.jsでやってみたことをまとめようと思います。
最初はNext.jsでやろうと思ったのですが、すでにMovable TypeのAdvent Calendarで公開されていたので、Nuxt.jsやろうと思います。
先日、Movable Type Advent Calendarで公開したプラグインNetlify Build Hooks を利用することでMTからビルドをh使いJamstackなサイトを作っていきます。
元々Movable Typeにはバージョン6のときからDataAPIが備わっており、API経由でデータを取り出したり送信することは可能なCMSになります。
MT自体は、表示側と管理画面が分離していることから使わないときはサーバを落としても配信先を別のサーバなどに設けておけばセキュアな環境で使うことも可能です。サーバ配信などもあるため

しかし、テンプレートを作るにはMovable Typeの独自タグ(MTML)で制御しHTMLを作らなければなりません。
前回作ったプラグインはNelifyのBuild Hooks用のプラグインではあるものの表示側をNext.jsやNuxt.jsでAPIを取得しつつ開発することが可能です。API自体はそもそも備わっているものになるため記事の更新時のHooksの呼び出しさえできればMovable TypeでもJamstackなサイトを構築できるといった感じになります。
今回はNuxt.jsを使いDataAPIを取得しつつ記事一覧・記事詳細画面を作っていきます。

今回のサンプルコード

Nuxt.jsのセットアップ

まずは、nuxt.jsの土台を作っておきます。プロジェクト名は nuxt-template-movabletype にしておきます。

yarn create nuxt-app nuxt-template-movabletype

公式のドキュメントにもある nuxt-app でとりあえず環境を用意しておきます。 ここで必要なものは axios だけも問題ありません。サンプルのコードは表示調整用に Tailwind CSS と Lint系で ESLintprettier はインストールしてあります。

環境変数を用意する

まずは、DataAPIの接続URLとそれにエンドポイント先となるサイトのIDを .env ファイルを作っておきます。
.env ファイルをルートに用意して各自のDataAPIのURLとサイトIDを入れておきます。
MY_DOMAINは、ご自身がインストールされたサイトのドメインをいれておきます。
MT_INSTALL_PATHは、インストールされたディレクトリを指定します。

BLOG_IDは、ここでは 1 をいれておきます。一番最初に作ったサイトは 1のIDが付与されます。
ちなみにSITE_IDだとNetlifyのMETAとかぶってしまうため明示的にBLOG_IDとしています。(接頭辞あったほうがいいかもですね)

API_URL=https://MY_DOMAIN/MT_INSTALL_PATH/mt-data-api.cgi/v4/sites/
BLOG_ID=1

次に、 nuxt.config.js ファイルに以下を追記します。
process.envで定義したAPIを変数に格納して、publicRuntimeConfigに取得した変数をセットしておきます。セットしておくことでコードからAPI_URLやBLOG_IDを参照できます。

const { API_URL, BLOG_ID } = process.env
export default {
  publicRuntimeConfig: {
    apiUrl: API_URL,
    siteId: SITE_ID,
  },
};

実際に取得して表示する

環境変数の用意ができれば、次は実際のコードに取得したデータを表示して記事詳細画面への遷移まで行っていきます。
Data APIには公式でリファレンスがあり、そちらから様々なデータを取得することができます。また認証を通すことでPOSTすることも可能です。

pages/index.vueを編集する

今回は自分の会社で運用しているMovableType Knowledgeからデータを取得した例になります。
環境変数からAPIのURLとサイトのIDを取り出して、entriesを叩くことで取得することができます。
こちらで記事のtitleとリンクを取得して遷移先を作ることができます。

<template>
  <div class="container mx-auto px-4">
    <h2 class="text-lg font-bold">ブログ記事</h2>
    <div v-for="(post, index) in posts" :key="index" class="grid grid-cols-3">
      <div>
        <a :href="`/blog/${post.id}/`">
          {{ post.title }}
        </a>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  async asyncData({ $axios, $config, error }) {
    try {
      const {
        data: { items },
      } = await $axios.get(`${$config.apiUrl}${$config.siteId}/entries`);
      return {
        posts: items,
      };
    } catch (err) {
      error({
        errorCode: 404,
      });
    }
  },
};
</script>

<style></style>

pages/blogs/_id.vueを編集する

_id.vueでブログ記事のIDをベースにファイルを作っておきます。
ここではタイトルと記事本文とMovable Type Knowledgeではカスタムフィールドを使っているため、その情報を取得しておきます。
タイトルと本文は、他のHeadlessCMSと変わらずかと思います。
Movable Typeのカスタムフィールドは customFieldsに情報が入っていきます。
他にもMovable Typeには、コンテンツタイプも存在してそちらを取得することも可能です。

<template>
  <div class="container mx-auto px-4">
    <h2 class="text-lg font-bold">{{ post.title }}</h2>
    <!-- eslint-disable-next-line vue/no-v-html-->
    <div class="body" v-html="post.body"></div>
    <!-- eslint-disable-next-line vue/no-v-html-->
    <div v-html="post.customFields[2].value"></div>
  </div>
</template>

<script>
export default {
  async asyncData({ $axios, $config, params, error }) {
    try {
      const { data } = await $axios.get(
        `${$config.apiUrl}${$config.siteId}/entries/${params.id}`
      );
      return {
        post: data,
      };
    } catch (err) {
      error({
        errorCode: 404,
      });
    }
  },
};
</script>

Netlifyに設定

セットアップは、他の記事でも紹介されているので、ここでは割愛します。
API_URLとBLOG_IDだけ設定して頂ければとMovable TypeのDataAPIを取得してgenerateすることができます。
また、以下のプラグインを作ったのでMTでDataAPIを更新するときは、こちらのプラグインからBuildを実行することが可能です。

やってみて

昨日は、MovableType.netでJamstackをやってみました。
あまり利用ケースする場面はあまりないと思いますが、サイト以外の活用だったり他のサイトで運用しているJamstackのサイトでMTデータを取得したい場面で活用しても良いかもしれません。
ちょっとした活用事例の紹介でした。