后端转全栈之Next.js SEO优化

2 阅读6分钟

本文概括:

  • Next.js SEO优化:用服务端组件、Streaming 渲染、next/image 和 next/font 提升加载速度和页面稳定性。
  • SEO 配置robots.txt 控制抓取,sitemap.xml 提供网站结构,可以主动推送Google,百度。
  • 页面 metadata:设置 titledescription,使用 Open Graph 优化分享。
  • 性能指标:关注 LCP ≤2.5秒,提高主要内容加载速度。

基本组件与 SEO 优化

在 Next.js 中,合理使用基础组件可以显著提升页面性能和 SEO 表现:

  1. 服务端组件(Server Components)

    • 尽量使用服务端组件,它们会在服务器直接渲染 HTML 并发送到前端,加快首次可视渲染,对 SEO 非常友好。
  2. Streaming 渲染

    • 使用 Streaming 渲染可以边生成边发送页面,不会影响 SEO,同时可以改善首页性能指标(如 LCP、TTFB)。
  3. Image 组件

    • 使用 next/image 组件加载图片,必须设置 alt 属性,既提升可访问性,也对 SEO 有益。
    • 默认会处理 布局偏移问题(Cumulative Layout Shift,CLS) ,确保页面稳定渲染。
  4. Font 组件

    • 使用 next/font 加载字体,可以避免 FOUT/FOIT(字体闪烁或延迟显示),同样减少布局偏移,提高用户体验和 SEO。
    • 默认也会阻止布局偏移,保持页面稳定。

SEO有关的配置文件

robots.txt

robots.txt 是网站根目录下的文本文件,用于告诉搜索引擎爬虫(如 Googlebot、Bingbot)哪些页面可以抓取,哪些页面不可以抓取。它是 网站爬虫控制协议(Robots Exclusion Standard)  的一部分。

在 SEO(搜索引擎优化)  中,合理设置 robots.txt 的核心目标是:

  1. 确保重要页面被抓取

    首页、栏目页、文章页、产品页等核心内容必须允许爬虫抓取。

  2. 阻止无关或重复内容抓取

    管理后台、用户隐私页、测试页、分页参数页、打印版页面等不需要被抓取,避免浪费爬虫抓取预算(Crawl Budget)并减少重复内容问题。

⚠️注意:如果爬虫抓了太多低价值页面,重要页面可能抓取不够,从而影响 SEO 效果。

# 允许所有爬虫
User-agent: *
# 禁止抓取管理后台和用户隐私页
Disallow: /admin/
Disallow: /login/
Disallow: /cart/
Disallow: /checkout/
# 禁止抓取参数化重复内容
Disallow: /*?sort=
Disallow: /*?filter=
# Sitemap 位置(告诉爬虫网站结构)
Sitemap: <https://www.example.com/sitemap.xml>

sitemap.xml

sitemap.xml 是一个 网站地图文件,主要作用是告诉搜索引擎你网站上的页面结构和更新频率,从而帮助搜索引擎 更快、更全面地抓取网站内容,对 SEO 非常重要。

robots.txt 告诉爬虫哪些页面不能抓,sitemap.xml 告诉爬虫 有哪些页面可以抓

常见的几个字段如下:

标签含义
<loc>页面 URL
<lastmod>页面最后修改时间,爬虫可以优先抓取更新过的内容
<changefreq>页面更新频率(alwayshourlydailyweeklymonthlyyearlynever
<priority>页面抓取优先级,0~1,1 表示最重要的页面

在Next.js中,可以使用 next-sitemap库,www.npmjs.com/package/nex…

参考配置即可 next-sitemap.config.js

/**
 * 使用文档地址 <https://github.com/iamvishnusankar/next-sitemap>
 */
/** @type {import('next-sitemap').IConfig} */
const config = {
  siteUrl: process.env.NEXT_PUBLIC_SITE_URL || "<https://next.anqstar.com>",
  generateRobotsTxt: true,
  sitemapSize: 7000,
  generateIndexSitemap: true,
  robotsTxtOptions: {
    policies: [{ userAgent: "*", allow: "/" }],
  },
};

export default config;

页面metadata

每个页面都需要取设置title,description等元信息:

可以参考Google的文档:developers.google.com/search/docs…

keywords 这种属性,Google 已经废弃不用了

SEO元数据

字段作用示例
<title>页面标题,搜索结果显示标题<title>我的博客 - 首页</title>
<meta name="description">页面描述,搜索结果摘要<meta name="description" content="这是我的技术博客,分享前端知识。">
<meta name="keywords">页面关键词(现代SEO已很少用)<meta name="keywords" content="前端, React, SEO">
<link rel="canonical">标准化URL,避免重复内容<link rel="canonical" href="<https://example.com/page>">
<meta name="robots">控制搜索引擎抓取和索引<meta name="robots" content="index,follow">

Open Graph

Open Graph(简称 OG)是 Facebook提出的一套网页元数据协议,目的是让网页内容在社交平台(如 Facebook、LinkedIn、微信、QQ 等)分享时,能够以 结构化、漂亮的卡片形式展示,而不仅仅是一个普通链接。

主要字段如下:

属性作用示例
og:title分享标题<meta property="og:title" content="我的博客首页">
og:description分享描述<meta property="og:description" content="前端开发教程分享">
og:image分享缩略图<meta property="og:image" content="<https://example.com/share.png>">
og:url网页链接<meta property="og:url" content="<https://example.com/page>">
og:type内容类型(website/article/video等)<meta property="og:type" content="website">
og:site_name网站名称<meta property="og:site_name" content="我的博客">

在Next.js框架中设置metadata:

文档:nextjs.org/docs/app/ge…

注意,需要在服务端组件中使用

静态metadata:

export const metadata: Metadata = {
    title: 'xxx',
    description: 'xxx',
}

动态metadata:

// app/market/[id]/page.js

interface PageProps {
  params: { id: string };
  searchParams: { q?: string };
}

// 注意这里是异步函数
export async function generateMetadata(
  { params, searchParams, parent }: PageProps & { parent?: Promise<Metadata> }
): Promise<Metadata> {
  // 获取父级 metadata(可选)
  const parentMetadata = parent ? await parent : {};

  // 根据 ID 请求接口获取资源信息
  const resource = await getResourceById(params.id);

  // 从 searchParams 获取搜索关键词
  const keyword = searchParams.q;

  return {
    // 可以继承父级 title
    title: resource?.title ? `${resource.title} - ${parentMetadata.title || "资源市场"}` : parentMetadata.title,
    description: resource?.description || parentMetadata.description || "高效开发资源市场",
    openGraph: {
      title: resource?.title || parentMetadata.title,
      description: resource?.description || parentMetadata.description,
      images: [resource?.cover || "/default.png"],
    },
  };
}

// 页面组件
export default async function ResourcePage({ params, searchParams }: PageProps) {
  const resource = await getResourceById(params.id);
  return (
    <div>
      <h1>{resource?.title}</h1>
      {searchParams.q && <p>搜索关键词: {searchParams.q}</p>}
    </div>
  );
}

Next.js Metadata 规则

在 Next.js App Router 中,可以在 templatelayoutpage 等页面定义 metadata。其规则如下:

  1. 优先级

    • 页面级 (page) 的 metadata 优先级最高,会覆盖同名的父级 layout 或 template metadata。
    • layout 或 template 中定义的 metadata 会作为默认值,如果子级没有覆盖,则会继承。
  2. 合并方式

    • 合并使用 浅合并(shallow merge)

      • 对象类型字段(如 openGraphtwitter)会被子级直接覆盖,不会递归合并。
      • 没有在子级定义的字段,会直接继承父级。
  3. 字段丢失注意

    • 如果子级 metadata 对象中没有某些字段,这些字段会从父级继承。
    • 但如果子级定义了该字段,则父级同名字段会被覆盖,原值不会保留。

例子:

// layout.tsx
export const metadata = {
  title: "我的网站",
  description: "网站默认描述",
  openGraph: {
    type: "website",
    images: ["/default.png"],
  },
};

// page.tsx
export const metadata = {
  title: "首页",
  openGraph: {
    title: "首页 OG", // 会覆盖 layout 的 openGraph
  },
};
  • 最终合并结果:
{
  title: "首页",
  description: "网站默认描述", // 继承自 layout
  openGraph: {
    title: "首页 OG", // 覆盖了整个 openGraph 对象
    // images 字段丢失了,因为浅合并不会保留 layout 的 images
  }
}

LCP指标

LCP(Largest Contentful Paint)  是 Web Vitals 中衡量页面加载性能的核心指标之一,用来衡量 页面主要内容加载完成的时间,也就是用户 能看到页面最大可视内容(通常是图片、视频或大块文本)  的时间,Google 推荐的 LCP 理想值

体验等级LCP 时间
优秀≤ 2.5 秒
需要改进2.5 – 4 秒
> 4 秒

在Next.js中,可以多使用Next.js 提供 next/image 组件,自带优化功能:

  • 自动压缩图片
  • 支持 WebP/AVIF 等现代格式
  • 懒加载(lazy loading)可选
  • priority 属性可提升 LCP 图片加载速度
import Image from 'next/image'

export default function Hero() {
  return (
    <div>
      <h1>欢迎访问我的博客</h1>
      <Image
        src="/hero.jpg"
        alt="首页大图"
        width={1200}
        height={600}
        priority
      />
    </div>
  )
}

其他优化SEO的办法

直接给Google,百度提交Sitemap文件

百度:ziyuan.baidu.com/site/index

Google:search.google.com/search-cons…