# Nextjs SEO Indexing

> 修复 Next.js 应用的 SEO 索引问题、抓取预算浪费和 Search Console 覆盖错误。涵盖 canonical 标签、noindex 审计、sitemap 健康、静态渲染和内链优化。触发词：SEO索引、Next.js索引、爬取预算、canonical修复、Search Console覆盖、noindex审计、sitemap健康

- Skill: `kscz0000/nextjs-seo-indexing` (Agent Skill)
- Install (CLI): `npx skillmds@latest add kscz0000/nextjs-seo-indexing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kscz0000/nextjs-seo-indexing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Marketing & Growth
- Author: kscz0000 (https://skillmd.com/u/kscz0000)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/kscz0000/nextjs-seo-indexing

---


# Next.js SEO 索引与抓取预算技能

修复 Next.js 应用中的 Google Search Console 覆盖问题、canonical 问题、sitemap 错误和抓取预算浪费。

---

## 何时使用

- 当 Next.js 站点出现 Google Search Console 覆盖问题（如重复 canonical、意外 noindex、抓取浪费或已发现但未索引的 URL）时使用。
- 在 SEO 发布前审计 sitemap、robots.txt、重定向、内链或静态渲染问题时使用。
- 当需要 Next.js App Router 的 metadata、`generateMetadata`、`robots.js` 和 sitemap 路由的框架级示例时使用。

---

## 理解 Search Console 覆盖状态

| 状态 | 含义 | 修复方式 |
|--------|---------|-----|
| 已抓取 – 未索引 | Google 已抓取但选择不索引 | 提升内容质量 + canonical + 内链 |
| 重复无 canonical | 多个 URL 提供相同内容，无 canonical | 在首选 URL 添加显式 canonical |
| 被 noindex 排除 | 存在 `noindex` 标签 | 如页面应被索引则移除 noindex |
| 重复，Google 选择了不同的 canonical | Google 偏好的 URL 与你指定的不同 | 将 canonical 与 Google 自然选择的 URL 对齐 |
| 带有正确 canonical 的备用页面 | 正常——非首选的重复页指向 canonical | 预期行为，无需处理 |
| 未找到 404 | 页面已删除或 URL 已变更 | 添加重定向或恢复页面 |
| 已发现 – 未索引 | Google 知道其存在但尚未抓取 | 改善内链 + 抓取预算 |
| 有重定向的页面 | 重定向链或重定向到错误目标 | 缩短重定向链，验证目标 |

---

## 第 1 步 — Canonical 审计

### Next.js App Router（metadata 导出）
```js
// app/blog/my-post/page.js
export const metadata = {
  title: 'My Post Title',
  alternates: {
    canonical: 'https://www.yourdomain.com/blog/my-post',
  },
};
```

### Next.js App Router（generateMetadata）
```js
export async function generateMetadata({ params }) {
  return {
    alternates: {
      canonical: `https://www.yourdomain.com/blog/${params.slug}`,
    },
  };
}
```

### 常见 canonical 错误及修复：
```js
// ❌ WRONG — relative URL
canonical: '/blog/my-post'

// ❌ WRONG — missing trailing slash inconsistency  
// (pick one and stick with it sitewide)

// ✓ CORRECT — absolute URL, consistent scheme + subdomain
canonical: 'https://www.yourdomain.com/blog/my-post'
```

---

## 第 2 步 — Noindex 审计

查找被意外 noindex 的页面：

```bash
# Search for noindex in metadata
rg -n --glob '*.{js,ts,jsx,tsx}' 'noindex|robots.*noindex' app pages

# Check layout.js — a noindex here affects ALL pages
grep -n "robots" app/layout.js
```

在 Next.js App Router 中，根 layout 中的 `robots` 全局生效。仅在需要全站控制时才在此设置。

```js
// app/layout.js — only set robots if you need sitewide control
export const metadata = {
  // ✓ Allow indexing
  robots: { index: true, follow: true },
  // ❌ This would noindex the entire site:
  // robots: { index: false }
};
```

---

## 第 3 步 — Sitemap 健康

### 验证 sitemap 路由返回 200 + 有效 XML
```bash
curl -sI https://www.yourdomain.com/sitemap.xml | grep -i "content-type\|status"
curl -s https://www.yourdomain.com/sitemap.xml | head -20
```

### Next.js App Router sitemap（推荐模式）
```js
// app/sitemap.js
export default async function sitemap() {
  const baseUrl = 'https://www.yourdomain.com';
  
  // Static pages
  const staticPages = [
    { url: baseUrl, lastModified: new Date(), changeFrequency: 'daily', priority: 1.0 },
    { url: `${baseUrl}/about`, lastModified: new Date(), changeFrequency: 'monthly', priority: 0.8 },
  ];
  
  // Dynamic pages (fetch from DB or CMS)
  const posts = await getPosts(); // your data fetch
  const dynamicPages = posts.map(post => ({
    url: `${baseUrl}/blog/${post.slug}`,
    lastModified: new Date(post.updatedAt),
    changeFrequency: 'weekly',
    priority: 0.7,
  }));
  
  return [...staticPages, ...dynamicPages];
}
```

### 多个 sitemap（sitemap index）
```js
// app/sitemap-tools/sitemap.js  
// app/sitemap-blog/sitemap.js
// Each returns an array of URL entries
```

---

## 第 4 步 — 静态渲染验证

页面必须静态生成（或 SSR 时 metadata 包含在 HTML 中），Google 才能看到 SEO 标签。

```bash
# Check build output — pages should show ● (static) not λ (dynamic)
npm run build 2>&1 | grep -E "○|●|λ|/blog|/tools"
```

```text
○  /about             (static)
●  /blog/[slug]       (SSG)  ← good
λ  /api/data          (serverless) ← expected for APIs
```

如果重要页面是 `λ`（完全动态，无静态生成），添加：

```js
// app/blog/[slug]/page.js
export async function generateStaticParams() {
  const posts = await getPosts();
  return posts.map(post => ({ slug: post.slug }));
}
```

---

## 第 5 步 — 内链审计

零内链的页面几乎不会被索引。每个重要页面应可通过以下途径到达：
1. 首页或导航
2. Sitemap
3. 至少一个其他内容页

```bash
# Find pages that have no inbound links from other pages
# (manual check — grep for the slug across all files)
grep -r "/blog/my-orphan-post" --include="*.{js,ts,jsx,tsx,md}" . | grep -v "sitemap\|the-page-itself"
```

---

## 第 6 步 — 重定向审计

```bash
# Find all redirects in Next.js config
grep -A 3 "redirects" next.config.js

# Check for redirect chains (A → B → C — should be A → C)
# Test a suspected chain:
curl -sI https://www.yourdomain.com/old-url | grep -i location
```

```js
// next.config.js — keep redirects flat (no chains)
async redirects() {
  return [
    {
      source: '/old-url',
      destination: '/new-url', // Must NOT itself redirect
      permanent: true, // 308 for SEO
    },
  ];
}
```

---

## 第 7 步 — robots.txt 检查

```bash
curl -s https://www.yourdomain.com/robots.txt
```

```text
# ✓ Good
User-agent: *
Allow: /
Sitemap: https://www.yourdomain.com/sitemap.xml

# ❌ Bad — disallows crawling of important content
Disallow: /blog/
Disallow: /tools/
```

```js
// app/robots.js (Next.js App Router)
export default function robots() {
  return {
    rules: { userAgent: '*', allow: '/' },
    sitemap: 'https://www.yourdomain.com/sitemap.xml',
  };
}
```

---

## 索引检查清单

- [ ] 所有关键页面都有绝对 canonical URL
- [ ] 无关键页面被意外 noindex
- [ ] Sitemap 路由返回 200 且 XML 有效
- [ ] Sitemap 已提交至 Google Search Console
- [ ] 关键页面在构建输出中为静态生成（●）
- [ ] 无重定向链（A→B→C 应为 A→C）
- [ ] robots.txt 允许抓取关键内容
- [ ] 每个关键页面至少有 1 条内链指向
- [ ] 已为已知 slug 的动态路由添加 `generateStaticParams`

## 局限性

- 不保证 Google 一定索引页面；最终索引决定权在搜索引擎。
- 需要访问代码库、已部署 URL，理想情况下还需 Google Search Console 数据才能做出可靠诊断。
- 涉及 URL 结构、重定向或 canonical 策略变更的建议会影响生产环境，部署前务必审查。

