Astro 的 SEO 优化有哪些特性?如何配置 Meta 标签、结构化数据和站点地图?
Astro 的 SEO 优化功能非常强大,帮助开发者构建搜索引擎友好的网站。了解如何利用 Astro 的 SEO 特性对于提高网站可见性至关重要。核心 SEO 优势:静态 HTML 输出:默认输出纯 HTML,易于搜索引擎爬取快速加载速度:零 JavaScript 默认,提升 Core Web Vitals服务器端渲染:支持 SSR,确保动态内容也能被索引语义化 HTML:鼓励使用正确的 HTML 标签Meta 标签配置:---// src/pages/index.astroconst title = "我的网站标题";const description = "这是网站描述";const image = "/og-image.jpg";const url = new URL(Astro.url.pathname, Astro.site);---<html lang="zh-CN"> <head> <!-- 基本 Meta 标签 --> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width" /> <meta name="description" content={description} /> <meta name="keywords" content="astro, seo, web development" /> <!-- Open Graph 标签 --> <meta property="og:type" content="website" /> <meta property="og:title" content={title} /> <meta property="og:description" content={description} /> <meta property="og:image" content={new URL(image, Astro.site)} /> <meta property="og:url" content={url} /> <!-- Twitter Card 标签 --> <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:title" content={title} /> <meta name="twitter:description" content={description} /> <meta name="twitter:image" content={new URL(image, Astro.site)} /> <!-- 规范链接 --> <link rel="canonical" href={url} /> <!-- Favicon --> <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" /> <!-- 结构化数据 --> <script type="application/ld+json" set:html={JSON.stringify({ "@context": "https://schema.org", "@type": "WebSite", "name": title, "url": url.toString(), "description": description })} /> </head> <body> <slot /> </body></html>动态 SEO 组件:---// src/components/SEO.astrointerface Props { title: string; description: string; image?: string; type?: 'website' | 'article'; publishedTime?: Date; modifiedTime?: Date; author?: string;}const { title, description, image = '/og-default.jpg', type = 'website', publishedTime, modifiedTime, author} = Astro.props;const url = new URL(Astro.url.pathname, Astro.site);const imageUrl = new URL(image, Astro.site);---<meta charset="UTF-8" /><meta name="viewport" content="width=device-width" /><meta name="description" content={description} /><meta name="robots" content="index, follow" /><!-- Open Graph --><meta property="og:type" content={type} /><meta property="og:title" content={title} /><meta property="og:description" content={description} /><meta property="og:image" content={imageUrl} /><meta property="og:url" content={url} />{publishedTime && <meta property="article:published_time" content={publishedTime.toISOString()} />}{modifiedTime && <meta property="article:modified_time" content={modifiedTime.toISOString()} />}{author && <meta property="article:author" content={author} />}<!-- Twitter Card --><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content={title} /><meta name="twitter:description" content={description} /><meta name="twitter:image" content={imageUrl} /><!-- Canonical --><link rel="canonical" href={url} /><!-- JSON-LD --><script type="application/ld+json" set:html={JSON.stringify({ "@context": "https://schema.org", "@type": type === 'article' ? 'Article' : 'WebSite', "headline": title, "description": description, "image": imageUrl.toString(), "url": url.toString(), "datePublished": publishedTime?.toISOString(), "dateModified": modifiedTime?.toISOString(), "author": { "@type": "Person", "name": author }})} />使用 SEO 组件:---// src/pages/blog/[slug].astroimport SEO from '../../components/SEO.astro';import { getEntry } from 'astro:content';const post = await getEntry('blog', Astro.params.slug);const { Content } = await post.render();---<SEO title={post.data.title} description={post.data.description} image={post.data.image} type="article" publishedTime={post.data.publishDate} modifiedTime={post.data.updatedDate} author={post.data.author}/><article> <h1>{post.data.title}</h1> <Content /></article>站点地图生成:// src/pages/sitemap.xml.tsimport { getCollection } from 'astro:content';export async function GET(context) { const posts = await getCollection('blog'); const site = context.site?.toString() || ''; const body = `<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> ${posts.map(post => ` <url> <loc>${site}blog/${post.slug}</loc> <lastmod>${post.data.updatedDate || post.data.publishDate}</lastmod> <changefreq>weekly</changefreq> <priority>0.8</priority> </url>`).join('')} <url> <loc>${site}</loc> <lastmod>${new Date().toISOString()}</lastmod> <changefreq>daily</changefreq> <priority>1.0</priority> </url></urlset>`; return new Response(body, { headers: { 'Content-Type': 'application/xml', 'Cache-Control': 'public, max-age=86400', }, });}Robots.txt 配置:// src/pages/robots.txt.tsexport async function GET(context) { const site = context.site?.toString() || ''; const body = `User-agent: *Allow: /Disallow: /api/Disallow: /admin/Sitemap: ${site}sitemap.xml`; return new Response(body, { headers: { 'Content-Type': 'text/plain', 'Cache-Control': 'public, max-age=86400', }, });}结构化数据:---// src/components/ArticleSchema.astrointerface Props { title: string; description: string; image: string; publishDate: Date; author: string; url: string;}const { title, description, image, publishDate, author, url } = Astro.props;---<script type="application/ld+json" set:html={JSON.stringify({ "@context": "https://schema.org", "@type": "Article", "headline": title, "description": description, "image": image, "datePublished": publishDate.toISOString(), "dateModified": publishDate.toISOString(), "author": { "@type": "Person", "name": author }, "publisher": { "@type": "Organization", "name": "My Website", "logo": { "@type": "ImageObject", "url": "/logo.png" } }, "mainEntityOfPage": { "@type": "WebPage", "@id": url }})} />面包屑导航:---// src/components/Breadcrumb.astrointerface Props { items: Array<{ name: string; href: string; }>;}const { items } = Astro.props;---<nav aria-label="Breadcrumb"> <ol class="breadcrumb"> {items.map((item, index) => ( <li class="breadcrumb-item"> {index === items.length - 1 ? ( <span aria-current="page">{item.name}</span> ) : ( <a href={item.href}>{item.name}</a> )} </li> ))} </ol></nav><script type="application/ld+json" set:html={JSON.stringify({ "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": items.map((item, index) => ({ "@type": "ListItem", "position": index + 1, "name": item.name, "item": new URL(item.href, Astro.site).toString() }))})} /><style> .breadcrumb { display: flex; list-style: none; padding: 0; margin: 1rem 0; } .breadcrumb-item:not(:last-child)::after { content: ' / '; margin: 0 0.5rem; } .breadcrumb-item a { color: #0066cc; text-decoration: none; } .breadcrumb-item a:hover { text-decoration: underline; }</style>性能与 SEO:---// src/pages/index.astroimport { Image } from 'astro:assets';import heroImage from '../assets/hero.jpg';---<!-- 优化图片加载 --><Image src={heroImage} alt="Hero Image" width={1200} height={630} format="webp" loading="eager" priority={true}/><!-- 预加载关键资源 --><link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin /><link rel="preconnect" href="https://api.example.com" /><!-- 内联关键 CSS --><style> /* 关键 CSS */ .hero { min-height: 60vh; }</style>最佳实践:Meta 标签:为每个页面设置唯一的 title 和 description使用 Open Graph 和 Twitter Card设置规范链接避免重复内容结构化数据:使用 JSON-LD 格式实现正确的 Schema 类型使用 Google 结构化数据测试工具验证性能优化:优化 Core Web Vitals使用图片优化实现代码分割内容优化:使用语义化 HTML优化标题层级(H1-H6)提供有意义的 alt 文本技术 SEO:生成站点地图配置 robots.txt实现面包屑导航Astro 的 SEO 功能帮助开发者构建搜索引擎友好的网站,提高在线可见性。