かめ。ブログ

NextでカテゴリなどgetStaticPropsを使って共通で定義したいけどできなかったので、別の方法での解決策

2021年10月4日
2022年1月10日

目次

pagesでカテゴリやタグをgetStaticPropsで定義していたのですが、
ページごとにjsonが吐き出されてしまって、共通にしたい内容なのにページごとのjsonに同じ内容が含まれてしまっていました。

_app.tsxgetStaticPropsを使って共通化すれば良いかなと思ったのですが、pages内でしか使えないようでした。
なので一工夫して解決してみました。

考え方

  • Nodeであらかじめ、microCMSの必要なデータを取得してjsonで吐き出しておく。
  • 使いたいところでjsonをimportして使う

実際のコード getMicroCMSdataについて

必要なもの

const fs = require('fs')
const axios = require('axios').default

const getMicroCMSdata = async (name, limit, query) => {
  const url = `https://${process.env.API_NAME}.microcms.io/api/v1/${name}`
  const apiKeyHeaderOption = { headers : { 'X-API-KEY': process.env.API_KEY }}

  const getUrlOption = (number, url) => {
    return url + `?limit=${number}${query}`
  }

  const getTotalCountUrl = getUrlOption(0, url)
  const totalCountUrlData = await axios.get(getTotalCountUrl, apiKeyHeaderOption).then(r => r.data)
  const { totalCount } = await totalCountUrlData

  const getContentUrl = getUrlOption(limit || totalCount, url)
  const contentUrlData = await axios.get(getContentUrl, apiKeyHeaderOption).then(r => r.data)
  const data = await contentUrlData

  return data
}

const generateIdsQuery = (ids) => {
  return `&ids=${ids.join(',')}`
}

const createJSONdata = async() => {
  const categories = await getMicroCMSdata('categories')
  const tags = await getMicroCMSdata('tags')
  const recentEntries = await getMicroCMSdata('entries', 5, '&orders=-publishedAt&fields=id,title,categories,tags,publishedAt,image,description')
  const recommendEntries = await getMicroCMSdata('entries', 5, `&ids=${generateIdsQuery(['imagealpha_imageoptim_jpegmini','photoshop_full_bloom','menta'])}&orders=-publishedAt&fields=id,title,categories,tags,publishedAt,image,description`)
  try {
    fs.writeFileSync('const/microcms.json', JSON.stringify({ categories, tags, recentEntries, recommendEntries }))
    console.log('create json!')
  } catch (e) {
    console.error(e);
  }
}

createJSONdata()

package.jsonの記述

build時にyarn generateCmsDataを合わせて実行するようにしています。 (実行時はAPI_NAME=microCMSのKEY API_KEY=microCMSのKEYを指定する必要あり)

  "scripts": {
    "build": "yarn generateCmsData && yarn next build",
    "generateCmsData": "node ./utils/serverGenerateCmsData"
  },

実行方法

下記のような感じurilsserverGenerateCmsDataをいれてNAME,KEYを入れて実行します。

API_NAME=microCMSのKEY API_KEY=microCMSのKEY yarn generateCmsData

getMicroCMSdataの引数

材料
nameapi名
limit取得したい件数(指定しない場合は全件)
queryフィルターや降順、昇順などの指定

コードの説明

まず件数を0件で取得して、何件登録されているかのtotalCountを取得しています。

const getTotalCountUrl = getUrlOption(0, url)
const totalCountUrlData = await axios.get(getTotalCountUrl, apiKeyHeaderOption).then(r => r.data)
const { totalCount } = await totalCountUrlData

limitがある場合はlimitの数分、存在しない場合は上でとってきたtotalCount分のデータを取得します

const getContentUrl = getUrlOption(limit || totalCount, url)
const contentUrlData = await axios.get(getContentUrl, apiKeyHeaderOption).then(r => r.data)
const data = await contentUrlData

api名 categoriesの全権を取得しています

const categories = await getMicroCMSdata('categories')

api名 tagsの全権を取得しています

const tags = await getMicroCMSdata('tags')

最新のentriesを5件、必要なfieldsを公開日順に取得しています

const recentEntries = await getMicroCMSdata('entries', 5, '&orders=-publishedAt&fields=id,title,categories,tags,publishedAt,image,description')

idsを使って自分で選んだ記事を取得しています

const generateIdsQuery = (ids) => {
  return `&ids=${ids.join(',')}`
}
const recommendEntries = await getMicroCMSdata('entries', 5, `&ids=${generateIdsQuery(['imagealpha_imageoptim_jpegmini','photoshop_full_bloom','menta'])}&orders=-publishedAt&fields=id,title,categories,tags,publishedAt,image,description`)

const/microcms.jsonにそれぞれ取得したjsonを文字列にして書き込んで吐き出すようにしました

fs.writeFileSync('const/microcms.json', JSON.stringify({ categories, tags, recentEntries, recommendEntries }))

吐き出したコードをを使う

実際に吐き出したjsonを使う場合はimportして使っています。

import cmsData from '~/const/microcms.json'

console.log(cmsData.categories.contents)

まとめ

下記参考にさせていただきました。

Nextデフォルトの機能で、共通で使えるgetStaticProps的なのがあればよいんですけどね。。 Nextも日々進化してるので、新しい機能でてきたら書き直したいですね。



関連する記事