ITエンジニアの種籾(たねもみ)

IT技術とか株式投資とか。

Gatsby.js の記事のURLに含まれるスラッグを階層化する

2020年 07月 20日

目次

記事が多くなることを考えるとローカルの記事のフォルダを階層化したいです。 年間どんだけ書くかわかりませんが、一つのフォルダ配下に 100 個も記事のフォルダがあったら扱いづらいです。

そこでローカルのフォルダ階層に従ったスラッグを生成するよう Gatsby.js で対応してみました。

階層ルール

ローカルのフォルダ階層に対応するとはいっても、ルールを決めておかないと後で困ります。 柔軟だと、その分大変だし。

スラッグは URL の一部なので公開した後は変えられません。 変えてしまったらリダイレクトしないと、Google も見に来るひとも辿れなくなってしまいます。

ある程度、永続して運用できるローカルフォルダの階層のルールと作り方を決めて対応します。

まず、ルールを決めました。

  • ローカルのフォルダ階層は2階層までで、${カテゴリ}/${記事名}
  • この場合のスラッグは${カテゴリ}-${記事名}

このカテゴリの決め方は次の通りにしました。

  • 迷ったらフォルダのカテゴリは分ける。
  • ローカルフォルダのカテゴリはサイト上のカテゴリとは別。
  • ローカルフォルダ上の複数のカテゴリをブログでは1つにしてもいい。
  • 反対にローカルフォルダが1つでもブログ上ではカテゴリをわけてもいい。
  • ブログ上のカテゴリは Markdown の frontmatter(YAML の部分)で変更できるようにする。

スラッグを作る

記事のスラッグを作っているのはgatsby-node.jsです。 ここを改修していきます。

gatsby-starter-blogからクローンしていれば、 スラッグを作るロジックは以下のようになっています。

exports.onCreateNode = ({ node, actions, getNode }) => {
  const { createNodeField } = actions;

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

ロジックを読むと、gatsby-source-filesystemプラグインのcreateFilePath APIを使って、 Markdown ファイルのノードからスラッグを作っています。

createFilePath の仕様を読むと、返ってくるのは Markdown ファイルが格納されているディレクトリ名でした。 なので、この API は使えませんので、簡単ではありますが記事のパスからスラッグを作ろロジックを自作します。

Markdown ファイルのノードにはfileAbsolutePathというファイルの絶対パスの属性があるので、 これを使って親ディレクトリともう一つ上のディレクトリからスラッグを作ればいいです。

実装はこんな感じです。

exports.onCreateNode = ({ node, actions }) => {
  const { createNodeField } = actions;

  if (node.internal.type === `MarkdownRemark`) {
    const value = createSlug(node.fileAbsolutePath);
    createNodeField({
      name: `slug`,
      node,
      value,
    });
  }
};

const createSlug = (filepath) => {
  const dirnames = filepath.split("/");
  const len = dirnames.length;
  return `/${dirnames[len - 3]}-${dirnames[len - 2]}`;
};

split かよと思いましたが、他にいいてはないし、ルールもしっかり決めたので十分です。

これを動かすと、

/Users/crz33/workspace/crz33-contents/blog/gatsby-blog/create-slug/index.md

という Markdown ファイルがあれば、

gatsby-blog-create-slug

というスラッグを作るようになりました。

記事の階層を変更する

カテゴリという階層を設けたので、それに合わせて記事のフォルダ階層を変更した。

こんな感じです。

フォルダ階層

以上です。

広告