かめ。ブログ

NextとmicroCMSでの「前の記事」「次の記事」の実装方法 

2021年9月28日
2022年2月25日

目次

microCMSでは現在直接「前の記事」「次の記事」」を再現するような、apiは提供されていないようです。
ただ工夫することで解決できるので、自分がやった方法を書いておきます
参考になればと思います。

一つ前 / 一つ後ろのコンテンツはどのように取得すれば良いですか?

こちらの公式の記事をを参考にしようと思ったのですが
queries: {limit: 1000, fields: 'id,title'}として1000件と指定して全て取ってくるようにするという方法が書かれています。

あまり全件取得ということはしたくないので別の方法をやってみました。

前提


実装時の考え方

  • 現在の記事を取得する
  • 現在の公開日より前、後の記事を1件だけフィルターを使って取得


こうすることで必要な1件のみを取得することができます。

client.ts

import { createClient } from 'microcms-js-sdk';

export const client = createClient({
  serviceDomain: process.env.API_NAME || '',
  apiKey: process.env.API_KEY || '',
})

microCMSで登録してある、「名前」「API_KEY」を入れてあげます。

記事部分のts「getStaticProps部分」

import { client } from '~/utils/client'
import { GetStaticProps } from 'next'
export const getStaticProps: GetStaticProps<Home, Params> = async (context) => {
  const id = context.params?.id

  const entry = await client.get<Entry>({ endpoint: 'entries', contentId: id})
  const fields = 'id,title,image,publishedAt'
  const prev = await client.get<EntriesApi>({
    endpoint: 'entries',
    queries: {
      limit: 1,
      orders: '-publishedAt',
      fields,
      filters: `publishedAt[less_than]${entry.publishedAt}`
    }
  })
  const next = await client.get<EntriesApi>({
    endpoint: 'entries',
    queries: {
      limit: 1,
      orders: 'publishedAt',
      fields,
      filters: `publishedAt[greater_than]${entry.publishedAt}`
    }
  })

  const prevEntry = prev.contents[0] || {}
  const nextEntry = next.contents[0] || {}

  return {
    props: {
      entry,
      prevEntry,
      nextEntry
    },
  }
}

getStaticPropsであらかじめ「前の記事」「次の記事」を取得してpropsで渡してあげるようにしています。

fieldsで使いたい部分のみ取得

const fields = 'id,title,image,publishedAt'

を指定することで必要な情報だけに絞ることができます。 こうしておくことで、api取得時にメインの記事の情報を含めないので、apiレスポンスが少し軽くなります。

記事apiレスポンスの型定義

export interface Entry {
  title: string
  description?: string
  id?: string
  publishedAt?: string
  updatedAt?:string
  body?: Body[]
  image?: ImageInfo
  thumbnail?: ImageInfo
  categories?: Category[]
  tags?: Tag[]
}
export interface EntriesApi extends ListApi {
  contents: Entry[]
}

自分で設定したfieldに合わせて型を用意します。

「前の記事」の実装

  const prev = await client.get<EntriesApi>({
    endpoint: 'entries',
    queries: {
      limit: 1,
      orders: '-publishedAt',
      fields,
      filters: `publishedAt[less_than]${entry.publishedAt}`
    }
  })
  • <EntriesApi>の部分でapiで返ってくる型を定義しています。
  • limit 1件のみ必要なので絞っています。
  • -publishedAt最新が欲しいので、公開日(publishedAt)で降順に。
  • filters: publishedAt[less_than]${entry.publishedAt}でフィルターをかける。この部分が重要になってきます。

「公開日:publishedAt」を「記事の公開日: entry.publishedAt」「より前: [less_than]」で取得というふうにフィルターをかけています。

「次の記事」の実装

  const next = await client.get<EntriesApi>({
    endpoint: 'entries',
    queries: {
      limit: 1,
      orders: 'publishedAt',
      fields,
      filters: `publishedAt[greater_than]${entry.publishedAt}`
    }
  })

「前の記事」と考え方は一緒です。差分としては [greater_than]のフィルター部分を[greater_than]に変更します。

「公開日:publishedAt」を「記事の公開日: entry.publishedAt」「より後: [less_than]」で取得というふうに変更してあげます。

まとめ

今回は「前の記事」「次の記事」に必要な部分だけを抜き出して説明しました。 microCMSで用意してくださっているsdkは、filterordersなど細かく設定できるようになっているので、工夫次第で色々できてよいですね。

公式で直接目的のapiが用意されていた場合はそちらを使えばいいのですが。 全部が用意されてるわけではないので、工夫しつつ再現できると良いですね。

今後もmicroCMSは色々と更新していってるようなので、いろいろなものが簡単に作るれるようになることに期待です!