发布于 2026-01-06 3 阅读
0

在 Next.js 中自动生成 sitemap.xml

在 Next.js 中自动生成 sitemap.xml

太棒了!您已经为美观且性能卓越的 Next.js 网站创建了所有组件和样式。接下来该做什么呢?

您希望在导出的包的根目录中提供一些关键文件,但 Next.js 默认只支持从/static文件夹复制文件。那么,如何添加例如 `<filename>` 文件sitemap.xml,即使是以自动化且始终保持最新状态的方式呢?

让我来向您展示如何为“yarn export”的 Next.js 项目进行设置。

基本的 sitemap.xml 结构

首先,我们需要了解一下一个基本的网站地图需要包含哪些信息。

一份清单……

  • 每个可用页面的网址
  • 以及相应的日期,以便搜索引擎机器人知道在哪里可以找到页面以及上次更改的时间。

就是这样!如果您想了解更多信息,可以查看谷歌的“构建和提交站点地图”网站

收集所需信息

在将文件写入导出的 /out 文件夹之前,我们需要先获取所需的信息:页面 URL 和最后修改日期。

为此,我编写了这个函数,它可以返回 /pages 文件夹内所有文件的路径:

module.exports = () => {
  const fileObj = {};

  const walkSync = dir => {
    // Get all files of the current directory & iterate over them
    const files = fs.readdirSync(dir);
    files.forEach(file => {
      // Construct whole file-path & retrieve file's stats
      const filePath = `${dir}${file}`;
      const fileStat = fs.statSync(filePath);

      if (fileStat.isDirectory()) {
        // Recurse one folder deeper
        walkSync(`${filePath}/`);
      } else {
        // Construct this file's pathname excluding the "pages" folder & its extension
        const cleanFileName = filePath
          .substr(0, filePath.lastIndexOf("."))
          .replace("pages/", "");

        // Add this file to `fileObj`
        fileObj[`/${cleanFileName}`] = {
          page: `/${cleanFileName}`,
          lastModified: fileStat.mtime
        };
      }
    });
  };

  // Start recursion to fill `fileObj`
  walkSync("pages/");

  return fileObj;
};
Enter fullscreen mode Exit fullscreen mode

这将返回一个对象,在我撰写本文时,该对象在我的网站上看起来像这样:

{
  "/blog/auto-generate-sitemap-in-next-js": {
    "page": "/blog/auto-generate-sitemap-in-next-js",
    "lastModified": "2018-10-03T00:25:30.806Z"
  },
  "/blog/website-and-blog-with-next-js": {
    "page": "/blog/website-and-blog-with-next-js",
    "lastModified": "2018-10-01T17:04:52.150Z"
  },
  "/blog": {
    "page": "/blog",
    "lastModified": "2018-10-03T00:26:02.134Z"
  },
  "/index": {
    "page": "/index",
    "lastModified": "2018-10-01T17:04:52.153Z"
  }
}
Enter fullscreen mode Exit fullscreen mode

如您所见,我们已经拥有构建网站地图所需的所有信息!

导出时创建文件

在 Next.js 中,创建静态文件包时,通常会运行 `.js` 命令yarn build && yarn export。我们希望在导出之后插入 `.js` 命令,以便在 `/out` 文件夹中创建 `sitemap.xml` 文件。

要接入 package.json 中定义的任何脚本,我们可以添加另一个同名脚本,但以“post”为前缀;

新的 package.json 文件中的 scripts 部分将如下所示:

...
"scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start",
    "export": "next export",
    "postexport": "node scripts/postExport.js"
  },
...
Enter fullscreen mode Exit fullscreen mode

我选择创建一个名为“scripts”的新文件夹,并在其中创建“postExport.js”文件。现在,每次调用“yarn export”后,该脚本都会运行。

生成 sitemap.xml 内容

scripts/postExport.js文件将利用我们之前创建的函数来获取所有需要的信息:

const pathsObj = getPathsObject();
Enter fullscreen mode Exit fullscreen mode

然后,我们将创建 sitemap.xml 文件:

const sitemapXml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> 
  ${Object.keys(pathsObj).map(
    path => `<url>
    <loc>https://embiem.me${path}</loc>
    <lastmod>${
      formatDate(new Date(pathsObj[path].lastModified))
    }</lastmod>
  </url>`
  )}
</urlset>`;

fs.writeFileSync("out/sitemap.xml", sitemapXml);
Enter fullscreen mode Exit fullscreen mode

就这样!嗯,差不多了。我用了 formatDate 函数,把日期转换成了想要的字符串格式。

你可以直接使用 `date` .substr(),因为它已经包含了 ISO 格式的日期,或者使用像date-fnspathsObj[path].lastModified这样的库。我决定从网上复制一个可行的解决方案:

module.exports = function formatDate(date) {
  var d = new Date(date),
    month = "" + (d.getMonth() + 1),
    day = "" + d.getDate(),
    year = d.getFullYear();

  if (month.length < 2) month = "0" + month;
  if (day.length < 2) day = "0" + day;

  return [year, month, day].join("-");
};
Enter fullscreen mode Exit fullscreen mode

现在运行yarn export,就会出现一个文件out/sitemap.xml

挑战!创建 robots.txt 文件

基于此,您现在应该很容易就能创建包含所需内容的 robots.txt 文件。

如果你想知道我是怎么做到的,请查看我网站仓库中的 scripts 文件夹。

如果你有其他解决办法,请告诉我。

后记

这是我在这社区的第一篇帖子👋。以后我会发更多帖子。你可以在我的博客上找到原文。

文章来源:https://dev.to/embiem/auto-generate-sitemapxml-in-nextjs-2nh1