简介
所以事情是这样的。我真的不想去关心SEO。这一切都很模糊,而且吸引了许多推销员。SEO网站是最糟糕的。然而,如果你想让人们看到你建立的东西,SEO仍然是超级重要的。
令人高兴的是,我们不需要成为SEO专家。一些关键的优化可以在我们的搜索引擎结果中发挥很大的作用!
在那篇文章中,作者解释了如何添加一个XML网站地图(除其他因素外*)帮助他们获得了显著的有机流量收益。因此,今天这个教程将指导你如何为你的Gatsby博客生成一个网站地图。
需要进行一些调整
这篇文章最初是在2020年初发布的,我听说这个插件在发布后有了一些变化
什么是XML网站地图?
XML网站地图是一个原始文件,旨在帮助机器了解一个网站的结构。它们看起来像这样。
这与有时在网站页脚链接的 "网站地图 "不同。人类是不会看这个的,也不应该链接到它们。这是一个专门为Googlebot和它的亲戚准备的文件。
利用生态系统
每当我在Gatsby项目中遇到一个新问题时,我的第一直觉总是去检查,看看社区是否已经创建了一个解决方案。快速搜索发现了[gatsby-plugin-sitemap],这是一个官方维护的插件,正好解决了这个问题。🎉
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
},
});
currentCategory
和canonicalCategory
变量对我来说已经可用了,因为我正在迭代我的所有数据并使用它来创建这些页面。
有了这个数据,我就可以更新传递给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
通过使用query
和serialize
,我们可以对生成的网站地图进行更好的控制。它还允许我们对一些特定页面的选项进行微调。
针对页面的选项
在生成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模板,以获得更漂亮的输出!因为它是一个较新的、不太经得起考验的插件,所以我选择在我的博客中坚持使用标准的插件,但对于有高级用例的人来说,这可能是一个强大的选择。
提交你的网站地图
一旦你的网站地图被生成,并且你的网站被部署,你就需要让谷歌知道它的存在。