如何在 React Router v7 中创建多语言站点地图

按语言组织站点地图以实现扩展

问题

站点地图可以帮助搜索引擎发现并抓取网站上的所有页面。一个拥有数百或数千个页面的多语言网站会迅速生成庞大的站点地图。将每种语言的所有 URL 列在一个文件中会变得难以管理,可能会超过 50,000 个 URL 或 50MB 的大小限制,并且使维护变得困难。当您更新某种语言的结构时,必须重新生成并重新验证整个文件。随着网站的增长,这种方法无法扩展。

解决方案

将站点地图拆分为一个层级结构,顶级站点地图索引指向单独的语言特定站点地图。每种语言都有自己的站点地图文件,仅包含该语言的 URL。索引文件充当目录,列出每种语言站点地图的位置。这种方法使单个文件易于管理,可以独立更新每种语言,并且在添加新语言或页面时具有良好的扩展性。搜索引擎会先抓取索引文件,然后跟随链接到每种语言的站点地图。

步骤

1. 创建站点地图索引路由

创建一个资源路由,返回列出所有语言特定站点地图的 XML 响应。

import type { Route } from "./+types/sitemap";

const LOCALES = ["en", "es", "fr", "de"];

export function loader({ request }: Route.LoaderArgs) {
const { origin } = new URL(request.url);

const sitemapIndex = `<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${LOCALES.map(locale => `  <sitemap>
  <loc>${origin}/sitemap-${locale}.xml</loc>
</sitemap>`).join("
")}
</sitemapindex>`;

return new Response(sitemapIndex, {
  headers: {
    "Content-Type": "application/xml",
  },
});
}

此路由作为 API 端点工作,通过返回 XML 响应。索引列出了每种语言的一个站点地图,通过更新 LOCALES 数组可以轻松添加或删除语言。

2. 创建特定语言的网站地图路由

定义一个带有动态段的资源路由,为每种语言生成单独的网站地图。

import type { Route } from "./+types/sitemap.$locale";

export async function loader({ params }: Route.LoaderArgs) {
const locale = params.locale;
const urls = await getUrlsForLocale(locale);

const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${urls.map(url => `  <url>
  <loc>${url}</loc>
</url>`).join("
")}
</urlset>`;

return new Response(sitemap, {
  headers: {
    "Content-Type": "application/xml",
  },
});
}

async function getUrlsForLocale(locale: string): Promise<string[]> {
return [];
}

路由路径中的动态段会被解析并作为 params.locale 提供。每种语言的网站地图仅包含该特定语言的 URL。

3. 获取每种语言的页面

实现一个辅助函数,从您的数据源中检索给定语言的所有页面。

async function getUrlsForLocale(locale: string): Promise<string[]> {
  const pages = await db.pages.findMany({
    where: { locale, published: true },
    select: { slug: true },
  });

  return pages.map((page) => `https://example.com/${locale}/${page.slug}`);
}

此函数会查询您的数据库或内容源中请求语言的已发布页面,并构建完整的 URL。根据您的应用程序调整查询和 URL 结构。

4. 注册网站地图路由

将网站地图路由添加到您的路由配置文件中。

import { type RouteConfig, route } from "@react-router/dev/routes";

export default [
  route("sitemap.xml", "./routes/sitemap.tsx"),
  route("sitemap-:locale.xml", "./routes/sitemap.$locale.tsx"),
] satisfies RouteConfig;

每个路由都有一个匹配的 URL 模式和一个指向路由模块的文件路径。索引路由响应 /sitemap.xml,语言路由响应 /sitemap-en.xml/sitemap-es.xml 等。

5. 将站点地图索引添加到 robots.txt

在公共目录的根目录下的 robots.txt 文件中,将搜索引擎指向您的站点地图索引。

User-agent: *
Allow: /

Sitemap: https://example.com/sitemap.xml

一个列出所有站点地图的站点地图索引可以让搜索引擎通过单一入口点发现所有特定语言的站点地图。搜索引擎会抓取该索引并自动跟随链接到每个语言的站点地图。