Gatsby

ReactのフレームワークGatsbyでサイトマップにlastmodを追加する方法

いつもご利用ありがとうございます。このブログは、広告費によって運営されています。

オススメ本
Web技術を勉強するなら、かなりオススメの雑誌です。毎月新しい発見があります。ついに最終号・・・、みなさん買いましょう!!
読んで損することはない名著。命名で悩むことが多い人はこの本がオススメです。

⇨ React 記事の目次はこちら

React のフレームワーク Gatsby のサイトマップに lastmod を追加して、更新日時をサイトマップに載せる方法を書いていきます。

使っているパッケージは

    "gatsby-plugin-sitemap": "^2.11.0",

です。もうすでにサイトマップは実装済みという前提になります。

また、md ファイルに rewritedAt という更新時間を記録している前提になります。

結論から

gatsby-config.js を修正します。

 {
      resolve: 'gatsby-plugin-sitemap',
      options: {
        query: `
          {
            site {
              siteMetadata {
                siteUrl: url
              }
            }
            allSitePage(
              filter: {
                path: { regex: "/^(?!/404/|/404.html|/dev-404-page/)/" }
              }
            ) {
              edges {
                node {
                  path
                }
              }
            }
            allMarkdownRemark(
              filter: { frontmatter: { template: { eq: "post" }, draft: { ne: true } } }
            ) {
              edges {
                node {
                  fields {
                    slug
                  }
                  frontmatter {
                    date
                    rewritedAt
                  }
                }
              }
            }
          }
        `,
        output: '/sitemap.xml',
        serialize: ({ site, allSitePage, allMarkdownRemark }) =>
          allSitePage.edges.map(
            edge => {
              const pages = allMarkdownRemark.edges;
              const index = pages.findIndex(
                x => edge.node.path.indexOf(x.node.fields.slug) != -1
              );
              var date;
              if (index != -1) {
                if (pages[index].node.frontmatter.rewritedAt) {
                  date = new Date(pages[index].node.frontmatter.rewritedAt);
                } else {
                  date = new Date(pages[index].node.frontmatter.date);
                }
              } else {
                date = new Date();
              }
              const year = date.getFullYear();
              const month = date.getMonth() + 1;
              const day = date.getDate();
              const lastmod = `${year}-${month}-${day}`;

              if (year == 1970) {
                return {
                  //もしmdファイルに更新日時がないとき
                  url: site.siteMetadata.siteUrl + edge.node.path,
                };
              } else {
                return {
                  //更新または作成日時がある時
                  url: site.siteMetadata.siteUrl + edge.node.path,
                  lastmod: lastmod,
                };
              }
            }
          )
      }
    },

解説

サイトマップを生成するもともとのコードが、

ブログで生成する全ての URL を map で回しつつ、その URL でサイトマップを回しているようでした。

この部分がサイトマップで URL を生成しているところでした。

url: site.siteMetadata.siteUrl + edge.node.path,

なので、map の中でパスと同じ slug を持つ posts を検索して、もし同じ slug があれば、rewritedAt があれば更新時間を入れる。

なければ date を更新時間に入れる。

という感じでやりました。なんとも力技ですが。

(もし、もっと大きなサイトで実装する場合はもっと詳細に検索する必要があると思います)

取得するデータを追加する

allMarkdownRemark(
              filter: { frontmatter: { template: { eq: "post" }, draft: { ne: true } } }
            ) {
              edges {
                node {
                  fields {
                    slug
                  }
                  frontmatter {
                    date
                    rewritedAt
                  }
                }
              }
            }

サイトマップを生成するためのデータ取得に post の md ファイル一覧を追加します。

必要な情報は、slug、date、rewritedAt のみっつです。

URL の数だけ回している map の中で post の slug と同じパスを持つものがあるか検索する

           edge => {
             //ページの一覧
              const pages = allMarkdownRemark.edges;
             //パスにページのslugが含まれていないかを検索
              const index = pages.findIndex(
                x => edge.node.path.indexOf(x.node.fields.slug) != -1
              );
              var date;
              //含まれていれば、更新日時or執筆日時(rewritedAtはnullの可能性がある)
              if (index != -1) {
                if (pages[index].node.frontmatter.rewritedAt) {
                  date = new Date(pages[index].node.frontmatter.rewritedAt);
                } else {
                  date = new Date(pages[index].node.frontmatter.date);
                }
              } else {
                //含まれていなければ基本ページなので伸びしろ。正しい更新時間をつけるのであればここは考える必要がある。もし考えるのがめんどうであれば、これらのページは更新時間未入力の方がいいか?
                date = new Date();
              }

コメントに記載した通りですが、URL のパスとマークダウンで作成している post の slug を検索して、lastmod に記述したい date を定義しています。

あとはサイトマップが読み込む形式にするだけ

const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const lastmod = `${year}-${month}-${day}`;

if (year == 1970) {
  return {
    //もしmdファイルに更新日時がないとき
    url: site.siteMetadata.siteUrl + edge.node.path,
  };
} else {
  return {
    //更新または作成日時がある時
    url: site.siteMetadata.siteUrl + edge.node.path,
    lastmod: lastmod,
  };
}

lastmod は

2021-08-22

のような形式だと読み込んでくれるので、そのようになるように整えて終わりです。

md ファイルに rewritedAt も date も無ければ year が 1970 になるので、その時は URL だけ送信します。

⇨Laravel でサイトマップを作る方法【SEO 対策】

⇨ サイトマップに priority と changefreq は不要っぽい

あとがき

だいぶ力技でしたが、なんとか実装することができました。

stackoverflow などでも検索した結果、みんな気合いで実装していそうだったので、僕も気合いで実装してしまいました。

lastmod はサイトマップの中では割と重要な肌感覚(記事の品質が新しいかどうかを判別する手段として有効)なので、めんどくさかったですが、実装しました。

しかし、(風の噂程度ですが)サイトマップのこう行った項目は、信憑性(クローラーが信用して読み込みに行ったページがそれと違っていた)が薄いと信用してもらえなくなるような感じだそうなので、慎重に正しく実装するのが良いと思います。

僕もそのうち、全体ページや個別ページでも対応したいと思います。

それでは!!!

質問、誤記などあれば Twitter などでご指摘よろしくおねがいします!

人気記事

PHP7.4 + Laravel6 のプロジェクトを AWS EC2 にデプロイする

関連記事

【ReactNative+CloudVision】「怒り顔採点アプリ」を作った