本文概括:
- Next.js SEO优化:用服务端组件、Streaming 渲染、
next/image
和next/font
提升加载速度和页面稳定性。 - SEO 配置:
robots.txt
控制抓取,sitemap.xml
提供网站结构,可以主动推送Google,百度。 - 页面 metadata:设置
title
、description
,使用 Open Graph 优化分享。 - 性能指标:关注 LCP ≤2.5秒,提高主要内容加载速度。
基本组件与 SEO 优化
在 Next.js 中,合理使用基础组件可以显著提升页面性能和 SEO 表现:
-
服务端组件(Server Components)
- 尽量使用服务端组件,它们会在服务器直接渲染 HTML 并发送到前端,加快首次可视渲染,对 SEO 非常友好。
-
Streaming 渲染
- 使用 Streaming 渲染可以边生成边发送页面,不会影响 SEO,同时可以改善首页性能指标(如 LCP、TTFB)。
-
Image 组件
- 使用
next/image
组件加载图片,必须设置alt
属性,既提升可访问性,也对 SEO 有益。 - 默认会处理 布局偏移问题(Cumulative Layout Shift,CLS) ,确保页面稳定渲染。
- 使用
-
Font 组件
- 使用
next/font
加载字体,可以避免 FOUT/FOIT(字体闪烁或延迟显示),同样减少布局偏移,提高用户体验和 SEO。 - 默认也会阻止布局偏移,保持页面稳定。
- 使用
SEO有关的配置文件
robots.txt
robots.txt
是网站根目录下的文本文件,用于告诉搜索引擎爬虫(如 Googlebot、Bingbot)哪些页面可以抓取,哪些页面不可以抓取。它是 网站爬虫控制协议(Robots Exclusion Standard) 的一部分。
在 SEO(搜索引擎优化) 中,合理设置 robots.txt
的核心目标是:
-
确保重要页面被抓取
首页、栏目页、文章页、产品页等核心内容必须允许爬虫抓取。
-
阻止无关或重复内容抓取
管理后台、用户隐私页、测试页、分页参数页、打印版页面等不需要被抓取,避免浪费爬虫抓取预算(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> | 页面更新频率(always , hourly , daily , weekly , monthly , yearly , never ) |
<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:
注意,需要在服务端组件中使用
静态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 中,可以在 template
、layout
、page
等页面定义 metadata
。其规则如下:
-
优先级
- 页面级 (
page
) 的metadata
优先级最高,会覆盖同名的父级layout
或template
metadata。 layout
或template
中定义的metadata
会作为默认值,如果子级没有覆盖,则会继承。
- 页面级 (
-
合并方式
-
合并使用 浅合并(shallow merge) :
- 对象类型字段(如
openGraph
、twitter
)会被子级直接覆盖,不会递归合并。 - 没有在子级定义的字段,会直接继承父级。
- 对象类型字段(如
-
-
字段丢失注意
- 如果子级
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文件