gatsby-starter-netlify-cmsのブログ記事のURLを指定できるようにする

GatsbyJSには様々なスターターが用意されており、gatsby-starter-netlify-cmsもその一つです。 このブログもgatsby-starter-netlify-cmsをカスタムして作られています。 基本的に痒いところに手が届く作りにはなっていますが、気になる箇所もいくつかあります。 今回は「gatsby-starter-netlify-cmsでブログ記事のURL」を自由に指定できるようにする方法を紹介します。

前提条件

  • gatsby-starter-netlify-cmsで作られた環境があること

そもそも記事URLとは?

記事URLは、個々の記事に割り当てられるURLのことです。 gatsby-starter-netlify-cmsで環境を一通り作った場合、記事の投稿はCMSの投稿画面から行う(≒自分で記事のmdファイルを作らない)わけですが、そうした場合に記事URLは「記事のmdファイル名」となります。 記事のmdファイル名はCMSの投稿作成画面で入力した「TITLE」になります。 つまり、デフォルトのままではこの記事のURLは"https://nekoniki.com/gatsby-starter-netlify-cmsのブログ記事のURLを指定できるようにする"になるということです。

cms_title

記事URLに日本語が入ってしまう点について、SEO的には問題ないのですが、エンコードされた時の見栄えが美しくない。 ※SNSに記事を投稿した際にエンコードされてるっぽいリンクが入るのが個人的にはどうも好かないです。

CMSで編集可能な項目を増やす

まず始めに取り掛かるのは、CMSの投稿画面で編集できる項目を増やすことです。 今回はQiita | Gatsby.js + NetlifyCMSのデータの流れまとめ(+投稿画面、URLのカスタマイズ)の記事を参考にsrc/statc/admin/config.ymlを修正しました。 少し解説をすると、collectionsというのがCMSで編集可能なページ区分一覧(デフォルトではpagesblogがある)で、その中のfieldsが対象ページを編集した際に画面から編集可能な項目です。 今回はblogfieldsurlを追加しています。

config.yml
collections:
  - name: "blog"
    label: "Blog"
    folder: "src/pages/blog"
    create: true
    slug: "{{year}}-{{month}}-{{day}}-{{slug}}"
    fields:
      - {label: "Template Key", name: "templateKey", widget: "hidden", default: "blog-post"}
      - {label: "URL", name: "url", widget: "string"} // これを追加
      - {label: "Title", name: "title", widget: "string"}
      - {label: "Publish Date", name: "date", widget: "datetime"}
      - {label: "Description", name: "description", widget: "text"}
      - {label: "Featured Post", name: "featuredpost", widget: "boolean"}
      - {label: "Featured Image", name: "featuredimage", widget: image}
      - {label: "Body", name: "body", widget: "markdown"}
      - {label: "Tags", name: "tags", widget: "list"}

正常に適用されればCMSの投稿画面にURLの項目が追加されています。

cms_url

入力したURLを反映させる

そもそも記事URLがどこで設定されているかという話になるのですが、大元はgatsby-node.jsにあります。

gatsby-node.js
exports.onCreateNode = ({ node, actions, getNode }) => {
  const { createNodeField } = actions
  fmImagesToRelative(node) // convert image paths for gatsby images

  if (node.internal.type === `MarkdownRemark`) {
    const value = createFilePath({ node, getNode })    createNodeField({
      name: `slug`,
      node,
      value,    })
  }
}

createFilePathで取得した値をslugという名前で作成しており、これがURLになっています。 なのでmdファイル名が記事URLになっているというわけです。

今回はgatsby-node.jsを修正し、先ほどCMSで設定できるようになったURLを使うようにしました。

gatsby-node.js
exports.onCreateNode = ({ node, actions, getNode }) => {
  const { createNodeField } = actions
  fmImagesToRelative(node) // convert image paths for gatsby images

  if (node.internal.type === `MarkdownRemark`) {
    const value = createFilePath({ node, getNode })
    const url = node.frontmatter.url // URLを取得    createNodeField({
      name: `slug`,
      node,
      // value,
      value: url? url : value // URLがあればそちらを使う    })
  }
}

これでCMSで設定したURLが記事URLに反映されるようになりました。

まとめ

今回はCMSの投稿作成画面でURLを自由に入力し、それが記事URLに反映されるようにしました。 当然ですが、このURLは一意である必要があるため、このブログでは基本的に「YYYYMMDD_xxx」の形式とするようルールを設けています。 この辺りは管理人の好みな部分も大きいので、ご自身のスタイルに合わせてご利用ください。

参考

SNSでシェアする