圣灯在线
2026-11-09· 10 分钟SEONext.js检查清单上线

Next.js 网站技术 SEO 检查清单(22 项,可逐条执行)

上线前逐条过一遍:可抓取性、内容结构、结构化数据、性能、国际化五大类共 22 项。每项给出检查命令、判断标准和修复方向,全部来自真实项目的实测。

这份清单来自实际项目:一个 126 页的站点改版,加上后来的双语重构。每一条都是踩过之后留下的。

用法:逐条过,打勾或标记问题。不要跳着看——第 1–8 条是基础,基础错了后面全白搭。


一、可抓取性(8 项)

1. 首轮 HTML 有没有正文

这是最容易出问题的一条。

curl -s https://your-site.com/page | python3 -c "
import sys, re, html
raw = sys.stdin.read()
m = re.search(r'<main[^>]*>(.*?)</main>', raw, flags=re.S|re.I)
seg = m.group(1) if m else raw
t = re.sub(r'<(script|style)[^>]*>.*?</\1>', ' ', seg, flags=re.S|re.I)
t = re.sub(r'<[^>]+>', ' ', t)
print('正文长度:', len(re.sub(r'\s+', ' ', html.unescape(t)).strip()))
"

判断:低于 500 字符就是有问题。真遇到过只有 46 个字符的页面(内容是 Loading…)。

原因:客户端渲染(CSR)。搜索引擎首轮不执行 JS,看到的是空壳。

修复:改用服务端组件,或在 page.tsx 里直接取数据渲染。


2. robots.txt 有没有误伤

curl -s https://your-site.com/robots.txt

判断:确认没有 Disallow: /,且 sitemap 地址正确。

坑:改版时把 /llms.txt 或 /sitemap.xml 挡掉。我遇到过 middleware 白名单没包含 .txt 的情况,导致对 AI 声明「本站已下线」。


3. sitemap 是否完整且可访问

curl -s -o /dev/null -w "%{http_code} %{size_download}\n" https://your-site.com/sitemap.xml
curl -s https://your-site.com/sitemap.xml | grep -c "<loc>"

判断:200,条数与实际页面数一致。

坑:lastmod 用 new Date()。每次部署全部 URL 都变成「今天更新」,Google 会判定不可信并最终忽略这个字段。要用内容真实更新日期。


4. 状态码是否正确

for u in / /about /nonexistent-page; do
  printf "%-20s " "$u"
  curl -s -o /dev/null -w "%{http_code}\n" "https://your-site.com$u"
done

判断:正常页 200,不存在页 404。

坑:把所有未知路径都返回 410。410 的语义是「永久删除」,用户拼错地址也返回 410,等于告诉搜索引擎这是有意删除,同时失去错误监控信号。

正确做法:确认删除的用 410,其他用 404。


5. canonical 是否自指

curl -s https://your-site.com/page | grep -o '<link rel="canonical"[^>]*>'

判断:指向自己,且是最终 URL(不是重定向前的)。

坑:/services/en 308 跳到 /en,但 canonical 写 /services/en。Google 会索引一个永远 308 的地址。


6. 有没有意外的 noindex

curl -s https://your-site.com/page | grep -o '<meta name="robots"[^>]*>'
curl -sI https://your-site.com/page | grep -i x-robots-tag

判断:正文页应该是 index, follow。


7. 重定向链是否只有一跳

curl -sIL https://your-site.com/old-page | grep -E "^HTTP|^location"

判断:不要出现 A → B → C 的链。


8. 静态资源是否被拦

curl -s -o /dev/null -w "%{http_code}\n" https://your-site.com/_next/static/chunks/main.js

判断:200。

坑:middleware 拦截规则写得过宽,把 /_next/static 也拦了,页面白屏。


二、内容结构(4 项)

9. H1 有且只有一个

curl -s https://your-site.com/page | grep -c "<h1"

判断:恰好 1 个。

为什么重要:我在 19 个美国中小企业站的抽样里发现,只有 7/13 恰好一个 H1,3 个完全没有——标题层级是搜索引擎判断页面主题的直接信号。


10. H2 有没有分节

判断:长文应该有 H2 分节,纯文本堆砌不利 AI 摘取。

坑:用 text-2xl font-bold 的 <div> 假装标题。视觉一样,机器读不出来。


11. 标题和描述有没有重复

curl -s https://your-site.com/sitemap.xml | grep -o '<loc>[^<]*' | sed 's|<loc>||' | while read u; do
  t=$(curl -s "$u" | grep -o '<title>[^<]*' | head -1)
  echo "$t | $u"
done

判断:每页 title 唯一。


12. 描述长度是否合适

判断:60–155 字符。太短浪费,太长被截断。

Next.js 里可以用 description.slice(0, 155) 统一控制。


三、结构化数据(4 项)

13. 有没有 JSON-LD

curl -s https://your-site.com/page | grep -o '"@type":"[A-Za-z]*"' | sort | uniq -c

判断:至少有一个与页面类型匹配的 schema。

页面类型 应该有的 schema
首页 Organization、WebSite
服务页 Service、FAQPage
文章页 TechArticle / Article、BreadcrumbList
商品页 Product、Offer

14. FAQPage 有没有标记

你页面上有 FAQ 折叠块,但没有 FAQPage schema,AI 就提取不到问答对。

修复:把 mainEntity 的 Question/Answer 结构加进去。


15. 实体是否声明了 provider

Service 里的 provider 要指向站点级的 Organization:

{
  "@type": "Service",
  "provider": { "@id": "https://your-site.com/#organization" }
}

用 @id 引用而不是重复声明实体——避免同一实体出现多个版本。


16. 报价有没有写进 schema

"offers": [
  { "@type": "Offer", "name": "入门", "price": "8000", "priceCurrency": "CNY" }
]

为什么:AI 回答「这个服务多少钱」时,有结构化报价的页面更容易被引用。


四、性能(4 项)

17. 核心指标是否达标

用 Lighthouse 实测,不是估算:

npx lighthouse https://your-site.com --output=json --output-path=lh.json --chrome-flags="--headless=new"
指标 目标
LCP < 2.5s
CLS < 0.1
TBT < 200ms

18. 图片是否用了现代格式

curl -s https://your-site.com/page | grep -o 'src="[^"]*\.\(png\|jpg\)"' | head -5

判断:界面截图应该用 WebP。

实测数据:四张 PNG 合计 955 KB,转 WebP 后 105 KB(11%)。纯色截图的压缩比能到 6%。


19. 有没有阻塞渲染的脚本

判断:首屏不应有同步 <script> 做布局修改。

真实案例:一段在 <head> 里改 lang 属性的脚本,让 TBT 从 60ms 涨到 240ms。改成静态标记后掉回 60ms。


20. 字体有没有本地化

坑:直接 @import 一个 8–10 MB 的中文字体包,LCP 直接崩。用系统字体栈,或只加载用到的子集。


五、国际化(2 项)

21. html lang 是否与页面语言一致

for u in / /en; do
  printf "%-6s " "$u"
  curl -s "https://your-site.com$u" | grep -o 'lang="[a-zA-Z-]*"' | head -1
done

判断:/ 是 zh-CN,/en 是 en。

这是最硬的一条。Next.js App Router 里 <html lang> 只能由根 layout 定义一次,要按路由切换必须拆 route group:

app/(zh)/layout.tsx   <html lang="zh-CN">
app/(en)/layout.tsx   <html lang="en">

用客户端脚本改 document.documentElement.lang 是无效的——搜索引擎首轮看到的是错的。


22. hreflang 是否双向且含 x-default

curl -s https://your-site.com/en | grep -o 'hrefLang="[^"]*"'

判断:每个语言版本都要列出全部语言,包括自己。另外要有 x-default 指向默认版本。

坑:页面级 metadata 会整段覆盖 layout 的 alternates,不是合并。重构后 /en 的 hreflang 消失就是这个原因。


快速自查

如果只有五分钟,查这四条:

  1. curl 首页看正文长度(第 1 条)
  2. curl /robots.txt(第 2 条)
  3. curl /sitemap.xml | grep -c loc(第 3 条)
  4. 查 html lang(第 21 条)

这四条出问题,其余优化都没有意义。


用工具代替手工

上面 22 条里,1、2、3、9、13、18 可以自动检查:

网站技术体检工具 —— 输入域名 30 秒出结果,不需要注册。

如果查出来问题较多、想系统修一遍,技术 SEO 体检与修复服务里写了完整流程和价格。

你的站有这些问题吗?

用免费体检工具输入域名,30 秒看结果。也可以直接写信说清情况,我告诉你值不值得修。