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

本文概括:

  • Next.js SEO优化 :用服务端组件、Streaming 渲染、next/imagenext/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 效果。

makefile 复制代码
# 允许所有爬虫
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> 页面更新频率(always, hourly, daily, weekly, monthly, yearly, never
<priority> 页面抓取优先级,0~1,1 表示最重要的页面

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

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

arduino 复制代码
/**
 * 使用文档地址 <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:

arduino 复制代码
export const metadata: Metadata = {
    title: 'xxx',
    description: 'xxx',
}

动态metadata:

typescript 复制代码
// 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 优先级最高,会覆盖同名的父级 layouttemplate metadata。
    • layouttemplate 中定义的 metadata 会作为默认值,如果子级没有覆盖,则会继承。
  2. 合并方式

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

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

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

例子:

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

// page.tsx
export const metadata = {
  title: "首页",
  openGraph: {
    title: "首页 OG", // 会覆盖 layout 的 openGraph
  },
};
  • 最终合并结果:
arduino 复制代码
{
  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 图片加载速度
javascript 复制代码
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...

相关推荐
牛仔只喝牛奶17 小时前
多端跨端技术选型:小程序 + H5 + App 的两栈拆分落地
react native·react.js
wear工程师20 小时前
setState 到底是不是异步的?这题从 React 16 问到 18,标准答案早就变了
react.js·面试
wanghowie1 天前
LangGraph4j 落地(二)— ReAct 多步工具与 trace 扩展
前端·react.js·前端框架
csj501 天前
前端基础之《React(11)—state声明式》
前端·react.js
张元清1 天前
React useLocalStorage Hook:SSR 安全的持久化状态(2026)
javascript·react.js
析数塔1 天前
2026前端框架深度解析:React Compiler、Angular Zoneless、Vue 3.5重写游戏规则
前端·vue.js·react.js
杖雍皓1 天前
没有服务器如何构建现代 Web 应用:平台选型与组合策略
运维·服务器·前端·react.js·github·netlify·vercel
sun_weitao1 天前
微前端框架之qiankun 怎么用?vue3+vite+qiankun 和 react + qiankun
前端·react.js·前端框架
名字还没想好☜2 天前
React useEffect 依赖数组踩坑:闭包陷阱与清理函数
前端·javascript·react.js·react·useeffect
我是大卫2 天前
【图】React源码解析-第四部分:事件与跨层传递
react.js·源码