Gatsbyで最終更新日時を表示する方法

4

目次

方法 1: 最終更新日時のフィールドを作成

手動ながら一番簡単。ブログ記事(md ファイル)の先頭に書くメタデータ群の中に modified-date を加える方法です。

hoge.md
---
template: BlogPost
path: /article-path
date: 2020-06-18T00:00:00.000Z
modified_date: 2020-06-19T00:00:00.000Z
title: 記事タイトル
category: dev
thumbnail:
metaDescription:
tags: ["ブログ", "Gatsby", "Node.js", "JavaScript"]
---

ここから文章が続く……。

こうすれば GraphQL で以下のように取得ができます。

graphQL
{
  "data": {
    "markdownRemark": {
      "frontmatter": {
        "date": "2020-06-18T00:00:00.000Z"
        "modified_date": "2020-06-19T00:00:00.000Z",
      }
    }
  }
}

あとはブログ記事のテンプレートファイル(blog.js)から GraphQL と出力ようコードを書けば OK です。

blog.js(スターターによってファイル名は異なります)
import React from "react";
/* 略 */

const blogPost = ({ data }) => {
  const { frontmatter } = this.props.data.markdownRemark;
  const date = frontmatter.date;
  const modifiedDate = frontmatter.modified_date;
  return (
    <Layout>
      {/* 略 */}
      <p>執筆日時: {date}</p>
      {date !== modifiedDate ? <p>最終更新日時: {modifiedDate}</p> : ""}      {/* 略 */}
    </Layout>
  );
};

export default blogPost;

export const pageQuery = graphql`
  query($path: String!) {
    略
    markdownRemark(frontmatter: { path: { eq: $path } }) {
      html
      frontmatter {
        date(formatString: "YYYY-MM-DD")
        modified_date(formatString: "YYYY-MM-DD")        略
      }
    }
  }
`;

方法 2: git の変更履歴から新規フィールドを作成

こちらの方法は方法 1 より実装難易度は上がるものの、自動的に最終更新日時を更新してくれるため、楽ちんだしヒューマンエラーが生じません。Github のファイル更新履歴を利用して最終更新日時のフィールドを作成する方法です。

難易度が上がるとはいえ、ほぼコピペで OK

gatsby-node.js に下記コードを追記します。

gatsby-node.js
const { execSync } = require("child_process");

// 略

exports.onCreateNode = ({ node, actions }) => {
  if (node.internal.type === "MarkdownRemark") {
    const gitAuthorTime = execSync(
      `git log -1 --pretty=format:%aI ${node.fileAbsolutePath}`
    ).toString();
    actions.createNodeField({
      node,
      name: "gitAuthorTime",
      value: gitAuthorTime,
    });
  }
};

これで GraphQL にallMarkdownRemark.edges.node.fieldsgitAuthorTimeが追加されます。これをテンプレートファイルから読み込めばいいだけ。

blog.js(スターターによってファイル名は異なります)
import React from "react";
/* 略 */

const blogPost = ({ data }) => {
  const { frontmatter, fields } = this.props.data.markdownRemark;  const date = frontmatter.date;  const modifiedDate = fields.gitAuthorTime;
  return (
    <Layout>
      {/* 略 */}
      <p>執筆日時: {date}</p>
      {date !== modifiedDate ? <p>最終更新日時: {modifiedDate}</p> : ""}      {/* 略 */}
    </Layout>
  );
};

export default blogPost;

export const pageQuery = graphql`
  query($path: String!) {
    略
    markdownRemark(frontmatter: { path: { eq: $path } }) {
      html
      frontmatter {
        date(formatString: "YYYY-MM-DD")
        略
      }
      fields {        gitAuthorTime(formatString: "YYYY-MM-DD")      }    }
  }
`;

おまけ

Gatsby にはデフォルトでaccessTimebirthtime,changeTimemodifiedTimeなどのファイルの変更日時に関するフィールドが用意されています。それらを利用すれば確かに方法 2 のようなことをしなくても Gatsby 純正の最終更新日時コンポーネントが作れるように思うかもしれません。事実、ローカルサーバーでは正常に動いていました。しかし、それらの便利なフィールドはファイルのタイムスタンプを利用しており、そのタイムスタンプというものは git には記録されません。Netlify では毎度git pullすることでデプロイしているわけですが、git にタイムスタンプ情報は含まれず、git pullを行なった日時がタイムスタンプとして記録されるので、すべての記事の最終更新日時は Netlify がgit pullした日となってしまうのです。そのため、Github に push して Netlify に自動デプロイするという手順をとっている場合は、別のアプローチをとる必要がありました。

参考記事

  • SNSでシェアしよう
  • Twitterでシェア
  • FaceBookでシェア
  • Lineでシェア
  • 記事タイトルとURLをコピー
トップへ戻るボタン

\ HOME /

トップへ戻る