根据git提交将LastMod添加到站点地图
#node #sitemap #lastmod #simplegit

这篇文章演示了基于git consits的lastmod时间戳丰富XML站点地图。

title image reading "Adding lastmod to sitemap based on git commits" with XML and Docusaurus logos

读取node.js中的git log

In the last post I showed how to manipulate XML in Node.js, and filter our sitemap。在这篇文章中,我们将基于上次所做的工作,阅读node.js中的git log,然后用它来为lastmod属性供电。

要读取node.js中的git log,我们将使用simple-git软件包。这是一个很棒的软件包,可以轻松阅读GIT日志。其他东西 - 但这就是我们今天关心的。

yarn add simple-git

要使用simple-git,我们需要创建一个Git实例。我们可以这样做:

import { simpleGit, SimpleGit, SimpleGitOptions } from 'simple-git';

function getSimpleGit(): SimpleGit {
  const baseDir = path.resolve(process.cwd(), '..');

  const options: Partial<SimpleGitOptions> = {
    baseDir,
    binary: 'git',
    maxConcurrentProcesses: 6,
    trimmed: false,
  };

  const git = simpleGit(options);

  return git;
}

从站点地图到git日志

值得暂停考虑我们的站点地图的样子:

<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
  <url>
    <loc>https://blog.johnnyreilly.com/2012/01/07/standing-on-shoulders-of-giants</loc>
    <changefreq>weekly</changefreq>
    <priority>0.5</priority>
  </url>
  <url>
    <loc>https://blog.johnnyreilly.com/2022/09/20/react-usesearchparamsstate</loc>
    <changefreq>weekly</changefreq>
    <priority>0.5</priority>
  </url>
  <!-- ... -->
</urlset>

如果您查看URL(loc),您可以看到确定原始markdown文件的路径相当容易。如果我们采用https://blog.johnnyreilly.com/2012/01/07/standing-on-shoulders-of-giants,我们可以看到Markdown文件的路径是blog-website/blog/2012-01-07-standing-on-shoulders-of-giants/index.md

只要我们没有播放的自定义sl(而且我很少这样做),我们就有一种可靠的方法可以从博客文章URL(loc)到Markdown文件。因此,我们可以使用simple-git获取该文件的git日志。然后,我们可以使用它来填充lastmod属性。

const dateBlogUrlRegEx = /(\d\d\d\d\/\d\d\/\d\d)\/(.+)/;

async function enrichUrlsWithLastmod(
  filteredUrls: SitemapUrl[]
): Promise<SitemapUrl[]> {
  const git = getSimpleGit();

  const urls: SitemapUrl[] = [];
  for (const url of filteredUrls) {
    if (urls.includes(url)) {
      continue;
    }

    try {
      // example url.loc: https://blog.johnnyreilly.com/2012/01/07/standing-on-shoulders-of-giants
      const pathWithoutRootUrl = url.loc.replace(rootUrl + '/', ''); // eg 2012/01/07/standing-on-shoulders-of-giants

      const match = pathWithoutRootUrl.match(dateBlogUrlRegEx);

      if (!match || !match[1] || !match[2]) {
        urls.push(url);
        continue;
      }

      const date = match[1].replaceAll('/', '-'); // eg 2012-01-07
      const slug = match[2]; // eg standing-on-shoulders-of-giants

      const file = `blog-website/blog/${date}-${slug}/index.md`;
      const log = await git.log({
        file,
      });

      const lastmod = log.latest?.date.substring(0, 10);
      urls.push(lastmod ? { ...url, lastmod } : url);
      console.log(url.loc, lastmod);
    } catch (e) {
      console.log('file date not looked up', url.loc, e);
      urls.push(url);
    }
  }
  return urls;
}

上面,我们使用正则表达式从URL提取日期和sl。然后,我们使用这些来构建通往降价文件的路径。然后,我们使用simple-git获取该文件的git日志。然后,我们使用最新的提交日期来填充lastmod属性,然后将其推到urls阵列。

最后,我们返回urls数组,然后将其写入站点地图,然后再写出来:

sitemap.urlset.url = await enrichUrlsWithLastmod(filteredUrls);

我们的新站点地图看起来像这样:

<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
  <url>
    <loc>https://blog.johnnyreilly.com/2012/01/07/standing-on-shoulders-of-giants</loc>
    <changefreq>weekly</changefreq>
    <priority>0.5</priority>
    <lastmod>2021-12-19</lastmod>
  </url>
  <url>
    <loc>https://blog.johnnyreilly.com/2012/01/14/jqgrid-its-just-far-better-grid</loc>
    <changefreq>weekly</changefreq>
    <priority>0.5</priority>
    <lastmod>2022-11-03</lastmod>
  </url>
  <!-- ... -->
</urlset>

您看到lastmod属性已根据该文件的最新提交为URL填充。是的!

github动作-fetch_depth

您可能认为我们已经完成了(我认为我们已经完成了),但我们不是。我们之所以没有完成,是因为我们正在使用github操作来构建网站。

当我在本地测试此测试时,效果很好。但是,当我将其推向GitHub动作时,它浮出水面的latest.date并没有带有您希望的价值。原因是fetch_depth设置为1(默认值)。这意味着GIT日志没有提供我们希望的信息。通过将fetch_depth更改为0,情况得到解决。

- uses: actions/checkout@v3
  with:
    # Number of commits to fetch. 0 indicates all history for all branches and tags.
    # Default: 1
    fetch-depth: 0