如何为你的Gatsby网站生成一个有利于SEO的网站地图

125 阅读9分钟

简介

所以事情是这样的。我真的不想去关心SEO。这一切都很模糊,而且吸引了许多推销员。SEO网站是最糟糕的。然而,如果你想让人们看到你建立的东西,SEO仍然是超级重要的。

令人高兴的是,我们不需要成为SEO专家。一些关键的优化可以在我们的搜索引擎结果中发挥很大的作用!

A graph showing the SEO impacts of moving a site to Gatsby

在那篇文章中,作者解释了如何添加一个XML网站地图(除其他因素外*)帮助他们获得了显著的有机流量收益。因此,今天这个教程将指导你如何为你的Gatsby博客生成一个网站地图。

需要进行一些调整

这篇文章最初是在2020年初发布的,我听说这个插件在发布后有了一些变化

什么是XML网站地图?

XML网站地图是一个原始文件,旨在帮助机器了解一个网站的结构。它们看起来像这样。

An HTML-like document shows a bunch of unintelligible markup. Upon close scrutiny, URLs from this blog can be seen.

这与有时在网站页脚链接的 "网站地图 "不同。人类是不会看这个的,也不应该链接到它们。这是一个专门为Googlebot和它的亲戚准备的文件。

利用生态系统

每当我在Gatsby项目中遇到一个新问题时,我的第一直觉总是去检查,看看社区是否已经创建了一个解决方案。快速搜索发现了[gatsby-plugin-sitemap],这是一个官方维护的插件,正好解决了这个问题。🎉

让我们用yarnnpm来安装它。

yarn add gatsby-plugin-sitemap

接下来,我们可以把它添加到我们的gatsby-config.js

module.exports = {
  siteMetadata: {
    // ✂️
  },
  plugins: [
    'gatsby-plugin-sitemap',
    // ✂️
  ],
}

每当我们建立网站时,这个插件就会生成一个sitemap.xml ,与Gatsby建立的所有其他文件一起。

重要的是,这个插件只在为生产构建时运行。这意味着,当你在开发模式下运行时,你将无法测试它。让我们来构建,并使用serve 来启动一个静态服务器。

yarn build && serve public

[serve](https://www.npmjs.com/package/serve)是一个NPM包,将在你的本地文件系统上提供文件。如果你以前从未使用过它,你首先需要用yarn add -g serve

我们把public 作为一个参数,因为Gatsby是在/public 目录下构建的;那是我们所有的静态文件将被提供的地方。

现在你应该能够打开localhost:5000/sitemap.xml ,并看到一个漂亮的丑陋的XML文档。

排除某些路径

除非你非常幸运,否则这个网站地图很可能并不完全正确。

添加网站地图的最大原因之一是告诉Google哪些页面不用担心。例如,我的博客在我的网站地图的原始版本中指定了以下网站。

<url>
  <loc>https://www.joshwcomeau.com/admin</loc>
  <changefreq>daily</changefreq>
  <priority>0.5</priority>
</url>
<url>
  <loc>https://www.joshwcomeau.com/confirmed</loc>
  <changefreq>daily</changefreq>
  <priority>0.5</priority>
</url>

admin 是我用来查看网站统计数据的认证途径, ,当用户加入我的通讯时显示。这两个页面包括在搜索结果中都没有意义。confirmed

令人高兴的是,我们可以定制该插件,以传递一个要排除的路径数组。

// gatsby-config.js
module.exports = {
  siteMetadata: {
    // ✂️
  },
  plugins: [
    {
      resolve: 'gatsby-plugin-sitemap',
      options: {
        exclude: ['/admin', '/confirmed'],
      },
    }
    // ✂️
  ],
}

高级定制

  • 在你的网站地图中只列出规范的URLs。如果你有一个页面的两个版本,在网站地图中只列出(谷歌选择的)规范的。

一个 "标准 "的URL是一个特定实体的 "真正的家"。如果你有多个包含相同内容的URL,你需要将其中一个标记为 "标准",供搜索引擎使用。

如果你这样做,谷歌会对你进行惩罚,而且会损害你的搜索结果排名😬。

除了这些网站地图的东西,用React Helmet在每个页面的头部添加一个<link rel="canonical"> 标签也是一个好主意。

在我的博客上,帖子的URL是以下格式:/:category/:slug 。这就出现了一个问题,因为帖子可能属于多个类别。例如,你现在正在阅读的文章可以通过这两个URL到达。

  • /gatsby/seo-friendly-sitemap/

  • /seo/seo-friendly-sitemap/

在帖子的前言中,我有这样的数据。

---
title: Generate an SEO-Friendly Sitemap for your Gatsby Site
type: tutorial
publishedOn: 2020-03-09T09:30:00-0400
categories: ['gatsby', 'seo']
---

类别是按优先顺序排列的,所以第一个类别应该总是形成规范的URL。

挑战很明显:我需要从我的MDX frontmatter中获取类别,并使用它来过滤网站地图中生成的站点。令人高兴的是,这是该插件的一个选项。

用GraphQL查询数据

在我们的gatsby-config.js ,我们可以写一个GraphQL查询来提取我们需要的任何数据。

module.exports = {
    siteMetadata: {
    // ✂️
  },
  plugins: [
    {
      resolve: 'gatsby-plugin-sitemap',
      options: {
        exclude: ['/admin', '/confirmed'],
        query: `
          {
            site {
              siteMetadata {
                siteUrl
              }
            }
            allSitePage {
              edges {
                node {
                  path
                }
              }
            }
          }
        `,
      },
    },
  ],
};

默认情况下,该插件使用这样的查询,但我们可以重写它。这里它获取了siteUrl ,在我的例子中是http://www.joshwcomeau.com ,然后它获取了每个页面节点的路径(例如:/gatsby/seo-friendly-sitemap )。它把它找到的每一个页面的这两个字符串拼接在一起,并产生一个网站地图。

为了过滤掉非经典的结果,我们首先需要将正确的数据暴露给GraphQL!

allSitePage 是创建的每个页面的索引,可以通过将React组件放入 ,或者使用 API。在我的案例中,我是用 ,以编程方式生成所有的文章/教程。src/pages createPage createPage

下面是一个典型的createPage 调用的样子,在gatsby-node.js

createPage({
  path: pathname,
  component: path.resolve(...),
  context: {
    /* component props */
  },
});

如果你正在用Markdown或MDX建立一个博客,你可能已经在使用它来生成你的页面。你提供给它一个path ,一个component ,以及一些组件可能需要的上下文数据。传递给context 的任何东西都可以通过props提供给component

令人高兴的是,事实证明,context 也被暴露在GraphQL中。

我向context 添加了一个新的数据。

createPage({
  path: pathname,
  component: path.resolve(...),
  context: {
    isCanonical: currentCategory === canonicalCategory
  },
});

currentCategorycanonicalCategory 变量对我来说已经可用了,因为我正在迭代我的所有数据并使用它来创建这些页面。

有了这个数据,我就可以更新传递给query 的GraphQL查询,在我的gatsby-config.js

query: `
  {
    site {
      siteMetadata {
        siteUrl
      }
    }
    allSitePage {
      edges {
        node {
          path
          context {
            isCanonical
          }
        }
      }
    }
  }
`,
GraphQL woes

GraphQL的困境

Gatsby开发者最常见的绊脚石之一是GraphQL。它是一个强大的工具,但它有一个相当陡峭的学习曲线。

筛选页面

现在,我们已经将每个页面的 "规范状态 "暴露给GraphQL,并将其写入gatsby-plugin-sitemap ,以便查询。这个难题的最后一块:覆盖默认的 "序列化器",以指定应该如何处理这些查询的数据。

下面是它的模样。

{
  resolve: `gatsby-plugin-sitemap`,
  options: {
    exclude: ['/admin', '/confirmed'],
    query: /* ✂️ */,
    serialize: ({ site, allSitePage }) => {
      return allSitePage.edges
        .filter(({ node }) => (
          node.context.isCanonical !== false
        ))
        .map(({ node }) => {
          return {
            url: site.siteMetadata.siteUrl + node.path,
            changefreq: 'daily',
            priority: 0.7,
          };
        });
    },
  },
}
serialize is a function th

serialize 是一个将来自 的数据转换为 "sitemappy "对象数组的函数。我们返回的项目将被用作生成网站地图的原始数据。query

现在我们已经在GraphQL中指定了它,我们可以访问node.context.isCanonical 来过滤掉重复的页面。

你会注意到我们正在明确地检查isCanonical 是否是false 。这一点很重要,因为isCanonical 将成为所有非博客帖子页面的undefined ,而这些页面完全值得包含在网站地图中。我们只想删除那些是false 的页面,而不是那些虚假的页面。

gatsby-plugin-sitemap通过使用queryserialize ,我们可以对生成的网站地图进行更好的控制。它还允许我们对一些特定页面的选项进行微调。

针对页面的选项

在生成XML网站地图时,你可能已经注意到有几个额外的字段被显示出来。

<url>
  <loc>https://www.your-website.com/page-1</loc>
  <changefreq>daily</changefreq>
  <priority>0.5</priority>
</url>
<url>
  <loc>https://www.your-website.com/page-2</loc>
  <changefreq>daily</changefreq>
  <priority>0.5</priority>
</url>

事实上,有一些选项可以用来调整每个页面,以达到最佳效果。

更改频率

changefreq 是衡量你的页面变化频率的一个标准。

这个值向搜索引擎提供一般信息,可能与他们抓取页面的频率不完全相关。有效值是。

  • 总是

  • 每小时

  • 每天

  • 每周

  • 每月

  • 每年

  • 从不

值 "always "应该用来描述每次访问都会改变的文件。值 "永不 "应该用来描述存档的URL。

对于一个博客来说,我觉得daily 很适合大多数的使用情况。

优先级

priority 是对一个页面的重要性的相对衡量。你可以用它来向爬虫发出信号,告诉它应该关心哪些页面,哪些不那么重要。有11个值可供你使用: 到 。0.0 1.0

如果你是一个聪明的捣蛋鬼,你可能正在构思一个狡猾的计划:把每个页面都设置为1.0 优先级,然后看着你的网站火箭般地上升到搜索结果的顶端!这就是你的计划。

不幸的是,这个计划并不奏效--priority 是一个相对的重要性衡量标准。它不会影响你的网站与其他网站的比较。

最后模式

最后,我们可以添加一个日期时间戳,以表明该页面最后一次被修改的时间。

老实说,我不确定这有多大价值,因为据推测,Googlebot足够聪明,可以检测到一个页面的内容是什么时候改变的,但正确地遵循一个规范是没有坏处的

进入兔子洞

如果你有兴趣了解还有什么其他的选择,或者如果你在调试问题时被卡住了,我想我会分享一些我在研究本教程时做的挖掘工作。

gatsby-plugin-sitemap 在写这篇文章的时候,它依赖于一个过时的1.13版本的NPM包,即 。sitemap

甚至更多的定制功能

如果你觉得你被这个插件提供的选项所限制,Ghost的人创造了他们自己的高级网站地图插件。它使用了XSL模板,以获得更漂亮的输出!因为它是一个较新的、不太经得起考验的插件,所以我选择在我的博客中坚持使用标准的插件,但对于有高级用例的人来说,这可能是一个强大的选择。

提交你的网站地图

一旦你的网站地图被生成,并且你的网站被部署,你就需要让谷歌知道它的存在。