Logo文档

SEO优化

学习如何通过元数据、站点地图和国际化优化 NEXTDEVKIT 网站的搜索引擎表现

🏗️ SEO 系统架构

NEXTDEVKIT 的 SEO 系统结构如下:

src/
├── lib/
│   └── metadata.ts                # 集中式元数据管理
├── app/
│   ├── [locale]/
│   │   └── layout.tsx            # 带有元数据的根布局
│   ├── sitemap.ts                # 自动生成站点地图
│   └── robots.ts                 # Robots.txt 配置
├── config/
│   └── index.ts                  # 网站配置
├── messages/
│   ├── en.json                   # 英文翻译
│   └── zh.json                   # 中文翻译
└── i18n/
    └── routing.ts                # 国际化路由

⚙️ 元数据配置

集中式元数据函数

NEXTDEVKIT 在 src/lib/metadata.ts 中提供集中式元数据函数:

import { appConfig } from "@/config";
import { getBaseUrl } from "@/lib/urls";
import type { Metadata } from "next";

export function metadata({
  title,
  description,
  image,
  canonicalUrl,
  keywords,
}: {
  title?: string | { template: string; default: string };
  description?: string;
  image?: string;
  canonicalUrl?: string;
  keywords?: string[];
} = {}): Metadata {
  title = title || appConfig.metadata.title;
  description = description || appConfig.metadata.description;
  image = image || appConfig.metadata.images?.ogImage;
  keywords = keywords || appConfig.metadata.keywords;
  
  const ogImageUrl = image.startsWith("/")
    ? new URL(`${getBaseUrl()}${image}`)
    : new URL(image);
    
  return {
    title,
    description,
    alternates: {
      canonical: canonicalUrl || "./",
    },
    keywords,
    openGraph: {
      type: "website",
      locale: "zh_CN",
      url: canonicalUrl || getBaseUrl(),
      title,
      description,
      siteName: appConfig.metadata.title,
      images: [ogImageUrl.toString()],
    },
    twitter: {
      card: "summary_large_image",
      title,
      description,
      images: [ogImageUrl.toString()],
      site: getBaseUrl(),
    },
    icons: [
      {
        rel: "icon",
        url: "/favicon-96x96.png",
        sizes: "96x96",
        type: "image/png",
      },
      { rel: "icon", url: "/favicon.svg", type: "image/svg+xml" },
      { rel: "shortcut icon", url: "/favicon.ico" },
      {
        rel: "apple-touch-icon",
        url: "/apple-touch-icon.png",
        sizes: "180x180",
      },
    ],
    metadataBase: new URL(getBaseUrl()),
  };
}

网站配置

src/config/index.ts 中配置您网站的基本 SEO 设置:

export const appConfig = {
	metadata: {
		name: "NEXT DEV KIT",
		title: "NEXTDEVKIT - Next.js 启动套件",
		description: "您下一个项目的终极 Next.js 启动套件",
		images: {
			logoLight: "/logo-light.svg",
			logoDark: "/logo-dark.svg",
			ogImage: "/og-image.png",
		},
		keywords: [
			"Next.js",
			"启动套件",
			"Next.js SaaS 模板",
			"Next.js 样板",
		],
	},
};

🌍 国际化元数据

基于翻译的元数据

NEXTDEVKIT 通过翻译文件支持国际化元数据:

// messages/en.json
{
  "app": {
    "metadata": {
      "title": "NEXTDEVKIT - Modern Next.js Starter Kit",
      "description": "A comprehensive Next.js starter kit with authentication, payments, and more"
    }
  }
}
// messages/zh.json
{
  "app": {
    "metadata": {
      "title": "NEXTDEVKIT - 现代 Next.js 启动套件",
      "description": "一个包含认证、支付等功能的综合性 Next.js 启动套件"
    }
  }
}

本地化布局元数据

在您的布局中生成本地化元数据:

src/app/[locale]/layout.tsx
import { metadata } from "@/lib/metadata";
import { getTranslations } from "next-intl/server";

export async function generateMetadata({
  params,
}: {
  params: Promise<{ locale: string }>;
}): Promise<Metadata> {
  const { locale } = await params;
  const t = await getTranslations({ locale, namespace: "app.metadata" });

  return metadata({
    title: {
      template: `%s | ${t("title")}`,
      default: t("title") || "",
    },
    description: t("description"),
  });
}

📄 特定页面元数据

基本页面元数据

为单独的页面添加元数据:

src/app/[locale]/pricing/page.tsx
import { metadata } from "@/lib/metadata";
import { getTranslations } from "next-intl/server";

export async function generateMetadata({
  params,
}: {
  params: Promise<{ locale: string }>;
}) {
  const { locale } = await params;
  const t = await getTranslations({ locale, namespace: "pricing" });

  return metadata({
    title: t("title"),
    description: t("description"),
    image: "/images/pricing-og.png",
    keywords: ["价格", "计划", "订阅", "nextdevkit"],
  });
}

export default function PricingPage() {
  return (
    <div>
      <h1>价格</h1>
      {/* 页面内容 */}
    </div>
  );
}

动态页面元数据

为动态页面生成元数据:

src/app/[locale]/blog/[slug]/page.tsx
export async function generateMetadata({
	params,
}: {
	params: Promise<{ slug: string[]; locale: Locale }>;
}): Promise<Metadata | undefined> {
	const { slug, locale } = await params;

	const blog = (await getBlogsFromParams(slug)) as any;

	if (!blog) {
		return {};
	}

	const t = await getTranslations({ locale, namespace: "blog" });

	return metadata({
		title: `${blog.title} | ${t("title")}`,
		description: blog.description,
		keywords: blog.keywords?.split(",") || [],
	});
}

🗺️ 站点地图生成

自动站点地图

NEXTDEVKIT 在 src/app/sitemap.ts 中自动生成站点地图。

🤖 Robots.txt 配置

Robots.txt 设置

src/app/robots.ts 中配置 robots.txt。

🖼️ Open Graph 图像

静态 OG 图像

将静态 Open Graph 图像放在 public 目录中:

public/
public/
├── og-image.png           # 默认 OG 图像 (1200x630)
├── apple-touch-icon.png   # Apple 触摸图标 (180x180)
├── favicon.ico           # 网站图标
├── favicon-96x96.png     # 高分辨率网站图标 (96x96)
├── favicon.svg           # SVG 网站图标

🔧 故障排除

常见 SEO 问题

缺失元标签

  • 确保实现了 generateMetadata 函数
  • 检查翻译是否正确加载
  • 验证元数据函数是否正确调用

重复内容

  • 设置正确的规范 URL
  • 对开发/测试环境使用 noindex
  • 实现正确的国际化

加载缓慢

  • 使用 Next.js Image 组件优化图像
  • 使用适当的加载策略
  • 实现关键 CSS 内联

Core Web Vitals 较差

  • 懒加载非关键图像
  • 最小化 JavaScript 打包大小
  • 使用高效的缓存策略

SEO 测试工具

使用这些工具测试您的 SEO 实现:

  • Google Search Console:监控搜索性能
  • PageSpeed Insights:检查 Core Web Vitals
  • Lighthouse:审核 SEO 和性能

🔗 相关资源


🎯 下一步

现在您了解了 SEO 系统,请探索这些相关功能: