在这篇文章中,我们将探讨如何向Next.js网站添加动态站点地图。我们将从使用"pages"目录添加站点地图开始,然后更新以利用Next.js版本13中引入的新"app"目录。我们的目标是实现一个动态站点地图,随着网站添加或删除页面而自动更新。这种方法对于SEO尤其有益,特别是对于定期更新内容的网站,如博客网站。
在深入实现细节之前,我们将简要讨论站点地图是什么,它们的用途,以及静态站点地图和动态站点地图之间的主要区别。通过阅读完本文,你将为Next.js 13网站拥有一个完全功能的动态站点地图。
什么是站点地图,我是否需要它?
站点地图是一个包含网站上所有页面列表及其相互关系的文件。它有助于搜索引擎爬取和理解网站的结构。站点地图还可以提供有关每个页面的重要信息,例如最后更新时间和更改频率。拥有站点地图对于规模较大或结构复杂的网站尤为重要,使搜索引擎更容易发现和索引所有页面。根据谷歌的说法,站点地图对于外部链接较少的新网站和内容链接较差的网站都是有益的。无论如何,站点地图都可以通过向搜索引擎提供有价值的信息以及增强站点导航来改善网站的SEO。
静态站点地图 vs 动态站点地图
站点地图主要有两种类型:静态和动态。静态站点地图是手动创建的,列出了网站上的所有页面。通常以XML格式创建,将此类型的站点地图提交给搜索引擎,以帮助它们发现和索引所有站点页面。相反,动态站点地图是网站服务器在添加或删除页面时自动生成和更新的。这种类型的站点地图对于规模较大或结构较复杂的网站特别有用,手动跟踪所有页面可能很困难。尽管两种类型的站点地图都有相同的目的,但动态站点地图通常更有效,因为它们消除了手动更新的需要。因此,我们将在Next.js网站中添加一个动态站点地图,当添加新页面时,例如发布新博客文章时,它将自动更新。
将站点地图添加到pages目录
首先,让我们讨论如何将站点地图添加到基于"pages"目录的站点。首先,在pages文件夹中创建一个sitemap.xml.js文件,并在其中添加一个默认的SiteMap组件。
javascript
// pages/sitemap.xml.js
export default function SiteMap() {}
此组件的唯一目的是在访问sitemap.xml端点时呈现站点地图页面。实际内容将来自getServerSideProps函数,该函数将获取所有帖子的URL,调用站点地图呈现函数,并使用text/xml内容类型标题写入响应。
javascript
// pages/sitemap.xml.js
import { getSortedPostsData } from "../lib/posts";
export async function getServerSideProps({ res }) {
const posts = getSortedPostsData();
// 用博客数据生成XML站点地图
const sitemap = generateSiteMap(posts);
res.setHeader("Content-Type", "text/xml");
// 将XML发送到浏览器
res.write(sitemap);
res.end();
return {
props: {},
};
}
export default function SiteMap() {}
这里getServerSideProps的目的是在访问/sitemap.xml URL时发送具有站点地图的自定义响应,因此我们为SiteMap组件返回一个空的props对象。getSortedPostsData是我们用于获取排序博客帖子的API。
最后一步是实现generateSiteMap函数,该函数将从所有帖子中提取URL,将链接添加到所有静态页面,并以XML格式呈现所有内容。
xml
// pages/sitemap.xml.js
import { getSortedPostsData } from "../lib/posts";
const URL = "https://www.nextjsboilerplates.com/";
function generateSiteMap(posts) {
return `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9">
<!-- 手动添加静态URL -->
<url>
<loc>${URL}</loc>
</url>
<url>
<loc>${URL}/portfolio</loc>
</url>
<url>
<loc>${URL}/blog</loc>
</url>
${posts
.map(({ id }) => {
return `
<url>
<loc>${`${URL}/blog/${id}`}</loc>
</url>
`;
})
.join("")}
</urlset>
`;
}
export async function getServerSideProps({ res }) {
const posts = getSortedPostsData();
// 用博客数据生成XML站点地图
const sitemap = generateSiteMap(posts);
res.setHeader("Content-Type", "text/xml");
// 将XML发送到浏览器
res.write(sitemap);
res.end();
return {
props: {},
};
}
export default function SiteMap() {}
在这里,我们只添加了URL,但你还可以添加其他属性,例如lastmod或priority。sitemaps.org有关于所有可能属性的更多详细信息。
另一点需要注意的是,我们将XML生成为字符串而不是JSX,因此在此处必须使用JavaScript模板文字。
确保用你自己的URL替换这些URL,并在启动应用程序并导航到yoursite.com/sitemap.xml后,你将能够看到动态生成的站点地图。
将站点地图添加到app目录
Next.js版本13引入了一个新的"app"目录,长期来看,它意味着取代了"pages"目录。由于这个变化,服务器端渲染(使用getServerSideProps)已被Server Components取代。在我们的情况下,这意味着我们不能再依赖getServerSideProps来呈现我们的站点地图页面。
Next.js 13.2及更低版本
幸运的是,在Next.js 13.2及更低版本中,我们可以使用Route Handlers来实现相同的行为。Route Handlers允许使用Web请求和响应API为特定路由创建自定义请求处理程序,它们用作"pages"目录的API路由的替代品。
深入阅读文档后,我们发现Route Handlers也可以用于返回非UI内容,这正是我们的站点地图所需的。首先,我们需要将sitemap.xml.js文件移动到app目录,并将其名称更改为route.js,这是定义Route Handlers的标准文件名。此外,我们将其嵌套在sitemap.xml文件夹中。
以下是旧"pages"和新"app"目录结构的比较:
arduino
// 之前
blog/
pages/
sitemap.xml.js
// 之后
blog/
app/
sitemap.xml/
route.js
之后,我们将修改route.js以创建此路由的自定义GET请求处理程序,该处理程序将返回具有生成的站点地图的自定义响应。此外,我们将不再需要getServerSideProps函数和SiteMap组件。
xml
// app/sitemap.xml/route.js
import { getSortedPostsData } from "../lib/posts";
const URL = "https://www.nextjsboilerplates.com/";
function generateSiteMap(posts) {
return `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9">
<!--手动设置我们已经知道的两个URL-->
<url>
<loc>${URL}</loc>
</url>
<url>
<loc>${URL}/portfolio</loc>
</url>
<url>
<loc>${URL}/blog</loc>
</url>
${posts
.map(({ id }) => {
return `
<url>
<loc>${`${URL}/blog/${id}`}</loc>
</url>
`;
})
.join("")}
</urlset>
`;
}
export function GET() {
const posts = getSortedPostsData();
const body = generateSiteMap(posts);
return new Response(body, {
status: 200,
headers: {
"Cache-control": "public, s-maxage=86400, stale-while-revalidate",
"content-type": "application/xml",
},
});
}
在这里,我们添加了1天的s-maxage和stale-while-revalidate指令。关于它们的更多信息,请参阅MDN。
Next.js 13.3及更高版本
Next.js版本13.3引入了基于文件的元数据API,通过导出元数据对象简化了处理页面元数据的工作。这不仅使管理静态和动态站点地图变得更容易,而且还消除了手动站点地图生成的需要。
为了利用这一点,我们可以创建一个名为sitemap.js的文件,该文件处理创建网站站点地图涉及的大部分重复逻辑。
arduino
// 之前
blog/
app/
sitemap.xml/
route.js
// 之后
blog/
app/
sitemap.js
在sitemap.js文件中,我们的主要任务是将帖子和静态URL映射到Sitemap对象的属性,并返回此对象。
javascript
// app/sitemap.js
import { getSortedPostsData } from "../lib/posts";
const URL = "https://www.nextjsboilerplates.com";
export default async function sitemap() {
const posts = getSortedPostsData.map(({ id, date }) => ({
url: `${URL}/blog/${id}`,
lastModified: date,
}));
const routes = ["", "/portfolio", "/blog"].map((route) => ({
url: `${URL}${route}`,
lastModified: new Date().toISOString(),
}));
return [...routes, ...posts];
}
此外,我们包括lastModified字段以显示每个页面的最后修改日期。当搜索引擎爬取和索引你的网站时,此信息对于它们非常有益。
通过进行这些更改,访问yoursite.com/sitemap.xml现在应该显示从"app"目录呈现的更新的站点地图。
总结
向网站添加站点地图是搜索引擎优化的重要方面,特别是对于较大的网站。它有助于搜索引擎理解站点的结构,发现所有页面并高效地爬取它们。
本文演示了如何向Next.js 13网站添加动态站点地图,该地图在添加或删除新页面时会自动更新。展示了如何使用"pages"或"app"目录为Next.js网站创建动态站点地图。
动态站点地图比静态站点地图更有效,尤其是对于较大或更复杂的网站。通过实施本文讨论的技术,你可以确保搜索引擎轻松发现你的网站,提高其整体SEO性能。