Gatsbyで最終更新日時を表示する方法
4分目次
方法 1: 最終更新日時のフィールドを作成
手動ながら一番簡単。ブログ記事(md ファイル)の先頭に書くメタデータ群の中に modified-date を加える方法です。
---
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 で以下のように取得ができます。
{
"data": {
"markdownRemark": {
"frontmatter": {
"date": "2020-06-18T00:00:00.000Z"
"modified_date": "2020-06-19T00:00:00.000Z",
}
}
}
}
あとはブログ記事のテンプレートファイル(blog.js)から GraphQL と出力ようコードを書けば OK です。
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 に下記コードを追記します。
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.fields
にgitAuthorTime
が追加されます。これをテンプレートファイルから読み込めばいいだけ。
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 にはデフォルトでaccessTime
、birthtime
,changeTime
、modifiedTime
などのファイルの変更日時に関するフィールドが用意されています。それらを利用すれば確かに方法 2 のようなことをしなくても Gatsby 純正の最終更新日時コンポーネントが作れるように思うかもしれません。事実、ローカルサーバーでは正常に動いていました。しかし、それらの便利なフィールドはファイルのタイムスタンプを利用しており、そのタイムスタンプというものは git には記録されません。Netlify では毎度git pull
することでデプロイしているわけですが、git にタイムスタンプ情報は含まれず、git pull
を行なった日時がタイムスタンプとして記録されるので、すべての記事の最終更新日時は Netlify がgit pull
した日となってしまうのです。そのため、Github に push して Netlify に自動デプロイするという手順をとっている場合は、別のアプローチをとる必要がありました。