首页 / Astro 教程 / SEO:meta 与 sitemap

Astro 教程

SEO:meta 与 sitemap

本教程共 56 篇 · 第 47 篇 · 更新于 2026-08-07 · 约 12 分钟阅读

AstroAstro 教程SEOmeta 标签sitemapOpen GraphHead 组件结构化数据

本节目标:搞懂 Astro 不会自动帮你写 SEO 标签这个事实,学会用一个 Head 组件统一管理 meta 信息,并配置 @astrojs/sitemap 自动生成站点地图,让搜索引擎更好地收录你的网站。

很多刚接触 Astro 的朋友会纳闷:「我在哪填网站标题和描述?是不是在 astro.config.mjs 里有个 SEO 字段?」答案是:没有这种字段。这一章先把这个最容易踩坑的点讲清楚,再给你一套标准做法。

先纠正一个常见误解

Astro 的配置文档(astro.config.mjs)只负责「怎么构建项目、怎么渲染 HTML」这类工程信息。它里面没有给搜索引擎或社交平台用的 SEO 字段,也没有「站点标题」「站点描述」这种配置项。

有人从别的框架过来,习惯在配置里塞一堆 meta。在 Astro 里这样做是错的。正确的做法是:像写普通 HTML 页面一样,用标准的 <link><meta> 标签,把 SEO 信息写进每个页面的 <head> 里。

那页面那么多,难道每个文件都手写一遍?当然不用。Astro 的答案是:抽一个 Head 组件。

用 Head 组件统一管理

<head> 里的内容(标题、描述、图标、社交分享卡等)每个页面都差不多,最干净的做法是做成一个 Head.astro 组件,放进共享布局(layout),由布局应用到所有页面。

Head 组件就是个普通 Astro 组件,它可以接收 props(比如当前页的标题)。下面是一个典型写法:

---
// src/components/Head.astro
const { title = "我的 Astro 网站", ...props } = Astro.props;
---
<title>{title}</title>
<meta name="description" content="欢迎来到我的新 Astro 站点!">
<link rel="sitemap" href="/sitemap-index.xml">
<!-- Open Graph 社交分享标签 -->
<meta property="og:title" content="我的新 Astro 网站" />
<meta property="og:type" content="website" />
<meta property="og:url" content="http://www.example.com/" />
<meta property="og:description" content="欢迎来到我的新 Astro 站点!" />
<meta property="og:image" content="https://www.example.com/_astro/seo-banner.webp">

然后在布局里引入它,放到 <head> 中:

---
// src/components/MainLayout.astro
import Head from "./Head.astro";
const { ...props } = Astro.props;
---
<html>
  <head>
    <meta charset="utf-8">
    <Head />
  </head>
  <body>
    <slot />
  </body>
</html>

每个页面只要在布局上传不同的 title 等 props,就能拿到专属的 meta,而不用重复写一堆标签。这就是零基础读者最该建立的心智模型:SEO 标签 = 普通 HTML 标签 + 一个可复用组件

关键 meta 标签清单

下面这些标签是 SEO 和社交分享的基础,逐项认识一下:

  • <title>:页面标题,SEO 里权重最高,搜索结果第一行显示的就是它。
  • <meta name="description">:页面描述,常作为搜索结果摘要出现。
  • <link rel="canonical">:规范 URL,告诉搜索引擎「这个页面的正式地址」,避免重复内容被分散权重。可以在布局里用 new URL(Astro.url.pathname, Astro.site) 动态生成。
  • Open Graph(og:title / og:type / og:url / og:description / og:image):社交平台(微信、Facebook 等)分享链接时显示的卡片信息。没它,分享出去就是个光秃秃的链接。
  • Twitter Card 标签(twitter:card 等):Twitter/X 平台的分享卡片,规则类似 Open Graph。
  • <link rel="icon">:网站小图标(favicon)。

这些标签直接写进 Head 组件即可,不需要任何特殊集成。Astro 在构建时会原样保留它们。

用 Astro.url 自动生成 canonical

规范链接(canonical)最怕写死——一旦你改了路由或部署到子路径,写死的地址就错了。更稳的做法是在 Head 组件里用 Astro.urlAstro.site 动态拼:

---
// src/components/Head.astro
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
---
<link rel="canonical" href={canonicalURL} />

Astro.url.pathname 是当前页面的路径(比如 /blog/hello/),Astro.site 是你在配置里填的域名。两者一拼,就得到绝对地址,无论部署到根域名还是子路径都不会出错。

favicon 与移动端视口

两个常被忽略但基础的标签也建议放进 Head 组件:

  • favicon(站点小图标):<link rel="icon" href="/favicon.svg" />。把图标文件放 public/ 目录,构建后会原样复制到根路径。
  • 移动端视口:<meta name="viewport" content="width=device-width, initial-scale=1.0" />。没有它,手机上页面可能按桌面宽度缩放,体验很差。一般布局里已经由模板带了,确认一下即可。

这些都属于「普通 HTML 标签」,Astro 不特殊对待,你按标准写法放进去就行。

验证你的 SEO 是否生效

写完标签,怎么确认没白写?两个简单办法:

  1. 本地 astro build 后,打开 dist/ 里对应的 .html,搜索 <title><meta name="description"><link rel="canonical">,看内容是否如预期。
  2. 部署后用浏览器的「查看网页源代码」(不是审查元素),确认 <head> 里确实有这些标签。搜索引擎读的是源代码,不是运行时 DOM。

如果某个页面的标题没变,通常是布局没把 title prop 传下去,或者 Head 组件里把 <title> 写死了。回到组件检查 props 传递即可。

站点地图 Sitemap 集成

光有 meta 还不够。网站页面多了,搜索引擎需要一张「地图」来高效爬取,这就是 sitemap(站点地图)。Astro 提供了官方集成 @astrojs/sitemap 自动生成它。

安装很简单,用官方命令一键搞定:

npx astro add sitemap

这条命令会装好包,并自动把集成写进 astro.config.mjs。手动装也行:

npm install @astrojs/sitemap

然后配置里要加一个关键的 site 字段——这是 sitemap 生成正确绝对 URL 的前提:

// astro.config.mjs
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';

export default defineConfig({
  site: 'https://www.example.com',
  integrations: [sitemap()],
});

注意 site 必须以 http://https:// 开头,填你正式部署的域名。构建(build)之后,输出目录里会出现 sitemap-index.xmlsitemap-0.xml。大站点还可能生成 sitemap-1.xml 等分片。

让爬虫更容易发现 sitemap

生成了 sitemap 还不够,最好主动告诉爬虫它的位置,有两处可加:

在页面 <head> 里放一个链接(放进 Head 组件):

<link rel="sitemap" href="/sitemap-index.xml" />

public/robots.txt 里声明(或动态生成):

User-agent: *
Allow: /

Sitemap: https://www.example.com/sitemap-index.xml

如果你不想维护静态文件,也可以在 src/pages/robots.txt.ts 里用端点动态拼出 robots.txt,复用配置里的 site 值,避免域名写死两遍。

排除不想被收录的页面

有些页面(比如后台、VIP 区域)不想进 sitemap。有两种办法。

第一,在该页 frontmatter 里设 sitemap: false

---
// src/pages/secret.astro
export const sitemap = false;
---

第二,在 sitemap 配置里用 filter() 函数批量过滤:

// astro.config.mjs
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';

export default defineConfig({
  site: 'https://example.com',
  integrations: [
    sitemap({
      filter: (page) =>
        page !== 'https://example.com/secret-vip-lounge-1/' &&
        page !== 'https://example.com/secret-vip-lounge-2/',
    }),
  ],
});

filter 会对每个页面调用一次,返回 true 收录、返回 false 排除。页面参数是带域名的完整 URL。

注意一点:@astrojs/sitemap 只能为静态生成的路由生成条目。SSR 模式下的动态路由它无法爬取,所以 sitemap 主要针对预渲染页面。

结构化数据 JSON-LD 思路

想让搜索结果显示更丰富的样式(如评分、面包屑),可以用结构化数据。Astro 没有内置生成器,需要你手写一段 JSON-LD(一种通用的结构化数据格式)注入页面。

做法是在布局 frontmatter 里定义 schema 对象,再用 set:html 指令把它塞进 <script type="application/ld+json">

---
const schema = {
  "@context": "https://schema.org",
  "@type": "WebSite",
  "name": "我的 Astro 网站",
  "url": Astro.site,
};
---
<script type="application/ld+json" set:html={JSON.stringify(schema)} />

这段内容对访客不可见,但搜索引擎能读懂,从而更好地理解你的站点。具体 schema 类型按业务去 schema.org 查即可,这里只讲接入方式。

小结:SEO 在 Astro 里是「手工但可控」

Astro 不替你生成 meta,初看麻烦,实则把控制权完全交给你:该写什么标签、怎么复用、怎么排除,都清清楚楚。记住这条主线——Head 组件管标签,sitemap 集成管地图,JSON-LD 管结构化数据,三者配合就能满足绝大多数内容的 SEO 需求。