Miobiki

  1. HOME
  2. javascript
  3. GatsbyJS月別archiveページ作成

GatsbyJS月別archiveページ作成

目次

このブログとは別件で個人ブログをwordpress v4.9.8とGatsbyJS v2で作成してます。
headless cmsというやつです。

gatsby.jsは静的サイトジェネレーターなのですがgatsby-source-wordpressプラグインを使うことで、wordpressから簡単に記事を引っ張ってこれます。
月別archiveページがほしくて、ちょっとだけ面倒なのですが自作したのでその紹介です。

ゴールはhttps://example.com/2018/09/ のようなURLで2018年9月の記事一覧ページを表示することです。

どちらで実装するか

  1. wordpressでAPIを拡張する方法
  2. gatsbyで全記事取得後、ゴニョゴニョする方法

gatsby側はなるべくシンプルにしたいと思い、wordpressのAPIを拡張することにしました。

API拡張失敗

結果から言うと、API拡張まではよかったのですが、gatsby側で取得ができなかったです。
拡張した時の実装方法に問題があったみたいですが、何故かはわかっていません!

/wp-json/wp/v2/archives を叩くと、以下のようなJSONが返ってくるように作成しました。

[
  {
    "id": 1,
    "slug": "2018/09",
    "year": "2018",
    "month": "09",
    "count": 2
  },
  {
    "id": 2,
    "slug": "2018/08",
    "year": "2018",
    "month": "08",
    "count": 3
  }
  ...
]

この場合GraphQLで allWordpressWpArchives フィールドが追加されるはずなのですが、一向にできません。

ブラウザからだとJSONが返ってくるのに…

どのように実装していたかというと、 wp_get_archives でhtmlを取得したあと、preg_matchで必要な部分だけ抜き出してJSONにしてました。
それを試しにget_postsに変更したところallWordpressWpArchivesで取得でき、wp_get_archivesを呼び出してしまうと駄目なことが分かりました。

phpでゴニョゴニョするなら、JSのほうが慣れているのでAPI拡張はやめることにしました。
wp_get_archivesでこんな風になれば楽だったのですが、諦めました。

wp_get_archivesを呼ばずにダミーのhtmlに差し替えて撮ったスクショ

JSでゴニョゴニョ

おおまかな流れはこんな感じです。

  1. 全件取得
  2. 日付だけ取り出す
  3. 重複削除 (Setがめちゃくちゃ便利!!)
  4. 日付の配列を回してcreatePage()

コードはこんなです。

// gatsby-node.js
exports.createPages = ({ graphql, actions }) => {
  const { createPage } = actions
  return new Promise((resolve, reject) => {
    // 1. 全件取得
    graphql(`
      {
        allWordpressPost {
          edges {
            node {
              date(formatString: "YYYY/MM", locale: "ja")
            }
          }
        }
      }
    `).then(result => {
      if (result.errors) {
        console.log(result.errors)
        reject(result.errors)
      }
      
      // 2. 日付だけ取り出す
      const dates = result.data.allWordpressPost.edges.map(({ node }) => node.date)
      // 3. 重複削除
      const uniqueDates = Array.from(new Set(dates))
      // 4. 日付の配列を回してcreatePage()
      uniqueDates.forEach(date => {
        const r = date.match(/(\d{4})\/(\d{2})/u)
        const slug = r[0]
        const year = r[1]
        const month = r[2]
        createPage({
          path: `/${slug}/`,
          component: path.resolve(__dirname, 'src/templates/archive.js'),
          context: {
            title: `${year}${month}月`,
            date: `/${year}-${month}/`,
          },
        })
      })
      resolve()
    })
  })
}


// archive.jsのquery
query PostsByDate($date: String) {
  allWordpressPost(filter: {date: {regex: $date}}) {
    edges {
      node {
        slug
        id
        title
        date(formatString: "YYYY.MM.DD h:mm", locale: "ja")
        categories {
          name
        }
        tags {
          name
        }
      }
    }
  }
}

こんな感じで月別アーカイブページを作成することができました。

感想

  • API拡張失敗するとどうやってデバックすればいいか分からないため、めちゃくちゃハマった
  • allWordpressWpArchivesで取得できたときは、よくわからんがすげーと思った
  • http://localhost:8000/___graphql 楽しい
  • 作るだけならwordpressだけのほうが楽