nextjs-seo
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseNext.js SEO Optimization
Next.js SEO优化
Comprehensive SEO guide for Next.js 16+ applications using App Router.
Version: Updated for Next.js 16.1.3 (January 2026)
这是一份针对使用App Router的Next.js 16+应用的全面SEO指南。
版本: 已更新至Next.js 16.1.3(2026年1月)
Quick SEO Audit
快速SEO审计
Run this checklist for any Next.js project:
- Check robots.txt:
curl https://your-site.com/robots.txt - Check sitemap:
curl https://your-site.com/sitemap.xml - Check metadata: View page source, search for and
<title><meta name="description"> - Check JSON-LD: View page source, search for
application/ld+json - Check Core Web Vitals: Run Lighthouse in Chrome DevTools
为任意Next.js项目运行以下检查清单:
- 检查robots.txt:
curl https://your-site.com/robots.txt - 检查站点地图:
curl https://your-site.com/sitemap.xml - 检查元数据:查看页面源代码,搜索和
<title><meta name="description"> - 检查JSON-LD:查看页面源代码,搜索
application/ld+json - 检查Core Web Vitals:在Chrome开发者工具中运行Lighthouse
Essential Files
关键文件
app/layout.tsx - Root Metadata
app/layout.tsx - 根元数据
typescript
import type { Metadata, Viewport } from 'next';
// Viewport (separate export required in Next.js 14+)
export const viewport: Viewport = {
width: 'device-width',
initialScale: 1,
maximumScale: 5,
userScalable: true,
themeColor: [
{ media: '(prefers-color-scheme: light)', color: '#ffffff' },
{ media: '(prefers-color-scheme: dark)', color: '#0a0a0a' },
],
};
export const metadata: Metadata = {
metadataBase: new URL('https://your-site.com'),
title: {
default: 'Site Title - Main Keyword',
template: '%s | Site Name',
},
description: 'Compelling description with keywords (150-160 chars)',
keywords: ['keyword1', 'keyword2', 'keyword3'],
openGraph: {
type: 'website',
locale: 'en_US',
url: 'https://your-site.com',
siteName: 'Site Name',
title: 'Site Title',
description: 'Description for social sharing',
images: [{ url: '/og-image.png', width: 1200, height: 630, alt: 'Site preview' }],
},
twitter: {
card: 'summary_large_image',
title: 'Site Title',
description: 'Description for Twitter',
images: ['/og-image.png'],
},
alternates: {
canonical: '/',
},
robots: {
index: true,
follow: true,
},
};typescript
import type { Metadata, Viewport } from 'next';
// Viewport(Next.js 14+中需要单独导出)
export const viewport: Viewport = {
width: 'device-width',
initialScale: 1,
maximumScale: 5,
userScalable: true,
themeColor: [
{ media: '(prefers-color-scheme: light)', color: '#ffffff' },
{ media: '(prefers-color-scheme: dark)', color: '#0a0a0a' },
],
};
export const metadata: Metadata = {
metadataBase: new URL('https://your-site.com'),
title: {
default: '站点标题 - 主关键词',
template: '%s | 站点名称',
},
description: '包含关键词的有吸引力描述(150-160字符)',
keywords: ['关键词1', '关键词2', '关键词3'],
openGraph: {
type: 'website',
locale: 'en_US',
url: 'https://your-site.com',
siteName: '站点名称',
title: '站点标题',
description: '用于社交分享的描述',
images: [{ url: '/og-image.png', width: 1200, height: 630, alt: '站点预览图' }],
},
twitter: {
card: 'summary_large_image',
title: '站点标题',
description: '用于Twitter的描述',
images: ['/og-image.png'],
},
alternates: {
canonical: '/',
},
robots: {
index: true,
follow: true,
},
};app/sitemap.ts - Dynamic Sitemap
app/sitemap.ts - 动态站点地图
typescript
import type { MetadataRoute } from 'next';
export default function sitemap(): MetadataRoute.Sitemap {
const baseUrl = 'https://your-site.com';
return [
{
url: baseUrl,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 1,
images: [`${baseUrl}/og-image.png`], // Next.js 16 Image Sitemap
},
{
url: `${baseUrl}/about`,
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.8,
},
];
}typescript
import type { MetadataRoute } from 'next';
export default function sitemap(): MetadataRoute.Sitemap {
const baseUrl = 'https://your-site.com';
return [
{
url: baseUrl,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 1,
images: [`${baseUrl}/og-image.png`], // Next.js 16 图片站点地图
},
{
url: `${baseUrl}/about`,
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.8,
},
];
}app/robots.ts - Robots Configuration
app/robots.ts - Robots配置
typescript
import type { MetadataRoute } from 'next';
export default function robots(): MetadataRoute.Robots {
const baseUrl = 'https://your-site.com';
return {
rules: [
{
userAgent: '*',
allow: '/',
disallow: ['/api/', '/_next/', '/admin/'],
},
],
sitemap: `${baseUrl}/sitemap.xml`,
host: baseUrl,
};
}typescript
import type { MetadataRoute } from 'next';
export default function robots(): MetadataRoute.Robots {
const baseUrl = 'https://your-site.com';
return {
rules: [
{
userAgent: '*',
allow: '/',
disallow: ['/api/', '/_next/', '/admin/'],
},
],
sitemap: `${baseUrl}/sitemap.xml`,
host: baseUrl,
};
}Key Principles
核心原则
Rendering Strategy for SEO
SEO渲染策略
| Strategy | Use When | SEO Impact |
|---|---|---|
| SSG (Static) | Content rarely changes | Best - pre-rendered HTML |
| SSR | Dynamic content per request | Great - server-rendered |
| ISR | Large sites, periodic updates | Great - cached + fresh |
| CSR | Dashboards, authenticated areas | Poor - avoid for SEO pages |
| 策略 | 使用场景 | SEO影响 |
|---|---|---|
| SSG(静态生成) | 内容极少变更 | 最佳 - 预渲染HTML |
| SSR(服务器端渲染) | 每个请求需动态内容 | 优秀 - 服务器渲染 |
| ISR(增量静态再生) | 大型站点、定期更新 | 优秀 - 缓存+新鲜内容 |
| CSR(客户端渲染) | 仪表盘、认证区域 | 较差 - SEO页面应避免使用 |
Core Web Vitals Targets
Core Web Vitals目标
| Metric | Target | Impact |
|---|---|---|
| LCP (Largest Contentful Paint) | < 2.5s | Loading speed |
| INP (Interaction to Next Paint) | < 200ms | Interactivity |
| CLS (Cumulative Layout Shift) | < 0.1 | Visual stability |
| 指标 | 目标 | 影响 |
|---|---|---|
| LCP(最大内容绘制) | < 2.5秒 | 加载速度 |
| INP(交互到下一次绘制) | < 200毫秒 | 交互性 |
| CLS(累积布局偏移) | < 0.1 | 视觉稳定性 |
References
参考资料
- Metadata API: See references/metadata-api.md
- Sitemap & Robots: See references/sitemap-robots.md
- JSON-LD Structured Data: See references/json-ld.md
- SEO Audit Checklist: See references/checklist.md
- Troubleshooting: See references/troubleshooting.md
- 元数据API:查看 references/metadata-api.md
- 站点地图与Robots:查看 references/sitemap-robots.md
- JSON-LD结构化数据:查看 references/json-ld.md
- SEO审计清单:查看 references/checklist.md
- 故障排除:查看 references/troubleshooting.md
Common Mistakes to Avoid
需避免的常见错误
- Mixing next-seo with Metadata API - Use only Metadata API in App Router
- Missing canonical URLs - Always set
alternates.canonical - Using CSR for SEO pages - Use SSG/SSR for indexable content
- Blocking assets in robots.txt - Don't block CSS/JS needed for rendering
- Missing metadataBase - Required for relative URLs in metadata
- Viewport in metadata - Must be separate export in Next.js 14+
- Mixing metadata object and generateMetadata - Use one or the other, not both
- 同时使用next-seo与元数据API - 在App Router中仅使用元数据API
- 缺少规范URL - 始终设置
alternates.canonical - 对SEO页面使用CSR - 对可索引内容使用SSG/SSR
- 在robots.txt中阻止资源 - 不要阻止渲染所需的CSS/JS
- 缺少metadataBase - 元数据中的相对URL需要此配置
- 在元数据中设置Viewport - Next.js 14+中必须单独导出
- 同时使用元数据对象与generateMetadata - 二选一,不要同时使用
Quick Fixes
快速修复方案
Add noindex to a page
为页面添加noindex
typescript
export const metadata: Metadata = {
robots: {
index: false,
follow: false,
},
};typescript
export const metadata: Metadata = {
robots: {
index: false,
follow: false,
},
};Dynamic metadata per page
为每个页面设置动态元数据
typescript
export async function generateMetadata({ params }): Promise<Metadata> {
const product = await getProduct(params.id);
return {
title: product.name,
description: product.description,
};
}typescript
export async function generateMetadata({ params }): Promise<Metadata> {
const product = await getProduct(params.id);
return {
title: product.name,
description: product.description,
};
}Canonical for dynamic routes
为动态路由设置规范URL
typescript
export async function generateMetadata({ params }): Promise<Metadata> {
return {
alternates: {
canonical: `/products/${params.slug}`,
},
};
}typescript
export async function generateMetadata({ params }): Promise<Metadata> {
return {
alternates: {
canonical: `/products/${params.slug}`,
},
};
}