NewtとNuxt.jsで記事を取得してみる

プログラミングNuxt.js

Newtとは

現在Nuxt.jsでこのサイトを作ってまして当初はmicroCMSを使ってましたが、うちみたいに各ページまったく別のコンテンツの場合、さすがにAPI3個では足りなくなりました。まあ、できないことはないですが、さすがに管理しにくい。

というわけでNewtに変えてみたわけですが、ここは2022年3月に開始した新しいヘッドレスCMSで現在は無料プランでもAPIが無制限となっており、また、1つのスペースにApp、モデル、ビューという構成で非常に柔軟に対応できるところが気に入りました。

記事の取得

さて、microCMSにはNuxt.js用モジュールが用意されてましてシンプルに記事の取得が可能でした。そこでこのモジュールとGitHubにあるNewtのスターターのコードを参考にプラグインを作成してみることに。

まずはnewtcmsClient.jsと適当に名前を付けてpluginsフォルダに作成。とりあえず現段階では個別記事と記事一覧が取得できればOKなので、getArticleとgetArticlesの2つを用意し、Contextから利用できるようにします。


import { createClient } from 'newt-client-js'

class NewtCmsClient {

  async getArticle(_config, appUid, modelUid, slug) {
    const client = createClient({
      spaceUid: _config.spaceUid,
      token:    _config.token,
      apiType:  _config.apiType
    })
    try {
      const { items } = await client.getContents({
        appUid,
        modelUid,
        query: {
          depth: 2,
          limit: 1,
          slug,
        },
      })
      return items.length === 1 ? items[0] : null;
    } catch (err) {
      // console.error(err)
    }
  }

  async getArticles(_config, appUid, modelUid, search, query, ) {
    const client = createClient({
      spaceUid: _config.spaceUid,
      token:    _config.token,
      apiType:  _config.apiType
    })
    try {
      const _query = {
        ...(query || {}),
      }
      if (search) {
        _query.or = [
          {
            title: {
              match: search,
            },
          },
          {
            body: {
              match: search,
            },
          },
        ]
      }
      const { items } = await client.getContents({
        appUid,
        modelUid,
        query: {
          depth: 2,
          limit: 100,
          skip: 0,
          ..._query,
        }
      })
      return items
    } catch (err) {
      // console.error(err)
    }
  }
}

export default ({ app }, inject) => {
  inject('newtcms', new NewtCmsClient())
}

API Referenceを確認してみるとgetContentはcontentIdで取得するようです。うちは基本的にslugで取得するケースがメインだろうと考え、getContentsで個別記事も取得することに。

これにより、例えば記事一覧が欲しいページでは以下のように使えるようにしました。


export default {
  async asyncData({ $config, $newtcms }) {
    const data = await $newtcms.getArticles($config, 'appUid', 'modelUid')
    return { contents: data }
  },
  ...
}

個別記事(_slug.vue)のページではparams.slugからgetArticleに放り込んだら良いだけです。これで各ページがスッキリしました。

※6/16 修正:行儀の悪いコードだなぁと思ってましたんで書き直し。