静态网站SEO常见的八类问题:Astro、Next.js、Hugo建站后要自己补上的那些活

静态网站SEO常见的八类问题:Astro、Next.js、Hugo建站后要自己补上的那些活
张文保 23 分钟阅读 3,804 阅读
本文目录
  1. 静态站的SEO问题都是从哪冒出来的?
  2. AI写的站,问题藏得更深
  3. 尾斜杠和canonical为什么会打架?
  4. 两个框架的默认值就不一样
  5. 怎么修
  6. 站点地图、robots.txt和noindex怎么保持一致?
  7. robots.txt可能压根没有
  8. 用一个标记管住所有出口
  9. 图片和模板,一错就是一大片
  10. 图片绕开了优化流程
  11. 模板里的默认值会复制到每一页
  12. 页面写着404,服务器说200
  13. 原因出在单页应用的兜底文件
  14. 用不存在的网址去试
  15. 内链写法和性能,AI最容易越改越乱
  16. 同一个页面,五种链接写法
  17. 静态不等于快
  18. 从WordPress迁到静态站要防什么?
  19. 哪个静态框架对SEO更好?
  20. 常见问题解答
  21. 静态网站对SEO不利吗?
  22. 静态站最常见的SEO问题有哪些?
  23. 网址末尾带不带斜杠对SEO有影响吗?
  24. Next.js的trailingSlash默认是什么?
  25. 为什么404页面会返回200状态码?
  26. 怎么检查网站的404是不是真404?
  27. 静态站的站点地图怎么排除noindex页面?
  28. robots.txt能代替noindex吗?
  29. Astro、Next.js、Hugo哪个最适合SEO?
  30. 从WordPress迁到静态站要注意什么?
  31. 用AI生成的静态站要特别检查什么?
  32. 权威参考资料

摘要:用Astro、Next.js、Hugo、Jekyll这类静态框架建站,WordPress插件默默替你做的canonical、站点地图、重定向、元数据、结构化数据和404处理,都变成了要自己配的活。Ahrefs的Despina Gavoyannis整理了静态站最常见的八类问题:尾斜杠和canonical打架、站点地图收录了noindex页面、图片绕开优化流程、模板一错错全站、看着是404实际返回200、内链写法不统一、静态构建照样可能很慢、从CMS迁过来丢了重定向。Ahrefs自己迁移博客时,就因为一条内链规则配错,把全站内链都加上了nofollow。

这两年用AI写代码搭网站的人越来越多,说一句“帮我用Astro做个官网”,十分钟页面就出来了,好看,打开飞快,部署到Vercel或Netlify还免费。不少外贸小团队和独立开发者都把官网从WordPress搬了过去。

建站变容易了,SEO可没跟着变容易。Ahrefs在10月1日发了一篇静态站SEO的长文,作者是Ahrefs高级SEO专家Despina Gavoyannis,还请了Keyword Insights联合创始人Suganthan Mohanadasan、geoSurge的SEO负责人Pedro Dias和Ahrefs的Ryan Law一起谈实战经验。这篇以那篇文章为主体,补上框架官方文档里的配置写法和自查命令。

静态站的SEO问题都是从哪冒出来的?

Suganthan的一句话把问题说透了:换成静态站,SEO的活并没有消失,只是挪了地方。WordPress把一大堆默认设置藏在插件后面,静态站把每一项都变成了你要亲手做的工作。

WordPress装个Yoast或者Rank Math,canonical、站点地图、标题模板、结构化数据、重定向、404页面,基本都有人管着。到了静态站,这些东西要么由框架提供一个半成品,要么完全没有,要么由AI在生成代码时顺手写了一个“看起来像那么回事”的版本。

这不代表静态站对SEO不好。静态站可以很快,代码也可以很干净。关键是你得知道原来的CMS替你做了什么,现在哪些要自己建、自己配、自己盯。

AI写的站,问题藏得更深

Ahrefs特别提到了用AI氛围编程(vibe coding)做出来的网站。AI能把页面做出来,但它不一定知道你希望全站遵守哪些SEO约定。今天让它加一个组件,明天让它改一个模板,每次它都可能用一套稍微不同的写法。页面在预览里看着都没问题,问题全在看不见的地方。

下面这张表是Ahrefs文章开头的总览,翻译整理如下:

问题为什么会发生没发现的后果
尾斜杠和canonical冲突托管平台和静态框架对网址末尾要不要斜杠的默认不一致重复网址,排名信号被分散
站点地图无视noindex站点地图可能收录了你不想出现在搜索里的页面草稿、感谢页之类的网址被收录
robots.txt缺失或配错不自己建,网站上线时可能根本没有这个文件该有的抓取规则缺了或者写错了
图片没优化绕开网站图片工具加进来的图,不会被自动缩放压缩页面变重、加载变慢、缺alt
元数据和结构化数据模板出错共享模板里一个错误,会出现在所有用它的页面上批量出现重复或过长的标题、错误元数据、坏掉的结构化数据
HTTP状态码不对404没配好,不存在的页面也返回200软404,浪费抓取
内链不统一不同模板和组件用不同写法链接同一个页面抓取混乱,内链信号被稀释
站点地图逻辑脆弱不同页面要不同规则时,基础配置很难管站点地图臃肿、缺页或格式错误
加载性能和核心网页指标差静态站照样可能加载多余的JavaScript或CSS加载变慢,核心网页指标变差

尾斜杠和canonical为什么会打架?

静态站很容易让同一个页面同时出现在两个网址上,比如/page和/page/。原因通常是框架和托管平台对尾斜杠的默认处理不一样:框架生成的是一种,托管平台提供或者重定向的是另一种。

这时候canonical标签、内链、重定向三者就可能各说各话。轻一点,多出一堆没必要的跳转;重一点,搜索引擎看到两份重复网址,排名信号被分到两边。同一个页面能有多少种网址写法,站里那篇11种写法都返回200做过完整的列举。

两个框架的默认值就不一样

拿两个最常用的框架看一下官方文档就明白了:

框架配置项默认行为
Next.jsnext.config.js里的trailingSlash默认会把带尾斜杠的网址重定向到不带的,比如/about/跳到/about;设成true就反过来,配合静态导出时/about会生成/about/index.html,默认生成的是/about.html
Astroastro.config里的trailingSlash默认ignore,/about和/about/都能匹配同一个路由;这个选项管的是开发服务器和按需渲染的页面,纯静态输出的文件形态另由build.format决定

Astro那条注意事项很容易被忽略。按Astro配置参考的说明,trailingSlash设成always或never时,生产环境里按需渲染的页面会被重定向到正确的网址,可纯静态生成的页面最后长什么样、托管平台怎么响应,还要看构建格式和平台自己的规则。在本地开发时一切正常,上线后行为变了,就是这么来的。

Next.js的trailingSlash文档写得很直接,配置就一行:

// next.config.js
module.exports = {
  trailingSlash: true, // /about 会 301 到 /about/
}

怎么修

Ahrefs给的办法分三步:选定一种网址格式,带斜杠或者不带,全站统一;把框架和托管环境都配成同一种约定;检查canonical标签和内链指向的是真正能直接打开的那个版本。

最快的验证是用curl看响应头,不带斜杠和带斜杠各请求一次:

curl -sI https://example.com/about | head -5
curl -sI https://example.com/about/ | head -5

理想结果是一个返回200,另一个返回301并在Location里指向前者,而且返回200的那个页面里,canonical写的也正是它自己。两个都返回200,就说明重复了。canonical只是给Google的提示,它不一定照办,具体可以看canonical的8种常见误用。

站点地图、robots.txt和noindex怎么保持一致?

静态站的XML站点地图通常是代码生成的,问题在于生成器不一定知道你把哪些页面设成了noindex。草稿、感谢页、订单确认页这类你不想出现在搜索里的网址,照样会被写进站点地图。

这在WordPress上很少发生,SEO插件会让站点地图和noindex设置保持同步。静态站没有这个插件,一个页面可能已经从导航里拿掉了,也加了noindex,却还待在站点地图和RSS里,除非你专门写了排除逻辑。

站点地图的逻辑还会随着网站长大变脆。一个扁平的小站点地图好管,可一旦要按页面类型拆分、排除某些目录、对不同模板用不同规则,配置就越来越难维护。站点地图里藏着多少坏网址,站里那篇585条网址里48条是坏的是个现成的例子,生成它的程序一次错都没报。

robots.txt可能压根没有

视框架和部署方式而定,robots.txt不一定会自动生成。上线前要确认这个文件存在,里面写的是你真正想要的抓取规则。Ahrefs也提醒了一句老话:robots.txt管的是抓取,管不了索引,别拿它代替noindex。

用一个标记管住所有出口

Ahrefs建议给不想进搜索的页面定一条统一规则,比如在页面的前置元数据里写noindex: true,然后让站点地图和RSS都跳过带这个标记的页面。robots.txt要指向正确的站点地图地址,也别误挡了想被抓取的目录。每次新增一种页面类型,或者改了页面生成方式,都要重新检查这套逻辑。

落到具体框架上,Jekyll常用的jekyll-sitemap插件支持在页面前置元数据里写sitemap: false来排除;Astro的站点地图集成提供filter选项,可以写函数过滤网址。思路都一样,让noindex和站点地图排除读同一个标记,别分两处手写。

图片和模板,一错就是一大片

图片绕开了优化流程

有些静态框架自带图片缩放、压缩和格式转换,但不是每个都有。Ahrefs举的例子是Jekyll,默认会把图片原样复制过去,不缩放、不压缩、不转格式,要优化就得装插件、接图片CDN,或者发布前单独处理一遍。

就算框架有图片工具,也只对走它那条流程的图片生效。Next.js通过next/image提供Image组件,会自动处理响应式尺寸、优化、懒加载和现代图片格式;可你要是直接写一个普通的img标签,这些就都得自己来。直接把原图丢进站点,等于完全绕过了这套流程。

结果就是两种问题:图片文件比需要的大得多,拖慢加载,手机上尤其明显;或者图片没有alt,读屏软件的用户不知道图上是什么,搜索引擎也少了理解图片的线索。最麻烦的是网站照样能构建成功,两个问题都不一定在发布前被发现。批量查alt的做法,可以看图片alt与属性的批量体检。

模板里的默认值会复制到每一页

静态站的标题、描述、canonical和结构化数据,通常由共享模板生成。管起来省事,可一个坏默认值能同时影响几百个页面。Ahrefs举了个很常见的例子:给所有标题自动加上品牌名,一整批页面的标题可能就超出了你想要的长度。

结构化数据也一样。模板里类型用错、缺了必填属性、关系结构写错,这个错误会被复制到每一个用这个模板的页面。Next.js允许在共享布局里定义一次标题模板,套用到很多页面,方便归方便,坏默认值扩散得也一样快。用过Yoast的人对这个思路不陌生,区别是Yoast给了一个专门管SEO规则的界面,静态站上你是直接把这套逻辑写进模板代码。

AI生成的模板更要小心,它可能给出一套看着合理的元数据和基础结构化数据,却和页面的真实类型、真实结构对不上。比如产品页套了Article,文章页的作者写成了公司名。

Ahrefs的修法是:建模板之前,先把每类页面需要哪些元数据和结构化数据定清楚;改了模板之后,挑好几个用这个模板的页面一起测,别只看一个。结构化数据可以用Google的富媒体搜索结果测试和Schema.org的验证工具过一遍。

页面写着404,服务器说200

这是静态站最隐蔽的一类问题:用户看到的是404页面,搜索引擎收到的状态码却是200。

Ahrefs引用了开发者Josh Deltener的记录。他的Nuxt静态站部署在Vercel上,页面上明明显示“404,页面未找到”,Chrome开发者工具里却显示请求返回200。Google会把这种情况当成软404:页面说自己不存在,服务器却报告成功。

原因出在单页应用的兜底文件

按Deltener的原文,问题来自Nuxt的Vercel适配生成的一个200.html。它是单页应用的兜底页面,用来接住构建时还不知道的路由,于是所有不存在的网址都由它来响应,状态码自然是200。如果你用nuxt generate把所有页面都预渲染了,构建时就知道全部页面,这个文件就用不着。他的做法是用nitro的配置钩子把它从预渲染路由里过滤掉:

// nuxt.config.ts
hooks: {
  'nitro:config'(config) {
    config.prerender!.routes = config.prerender!.routes!.filter((r) => r !== '/200.html')
  }
}

这段代码针对的是他那个具体环境,换了框架和平台,兜底机制不一样,修法也不一样。能通用的是检查方法。

用不存在的网址去试

建一个正经的404页面,然后随手编几个肯定不存在的网址,看真实的HTTP状态码。应该是404,光长得像404不算数:

curl -s -o /dev/null -w '%{http_code}\n' https://example.com/this-page-does-not-exist-123
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/blog/no-such-post

两条都该输出404。输出200的话,回头查托管平台的404配置和框架的兜底页面。Apache上错误页和状态码的关系,站里ErrorDocument与软404那篇讲过,原理相通。

内链写法和性能,AI最容易越改越乱

同一个页面,五种链接写法

不同模板、不同AI生成的组件,拼网址的方式可能都有点不一样。有的链到/about,有的链到/about/;有的用相对路径../about/,有的用绝对地址https://example.com/about/。这些写法单独看都没错,问题在于它们和你定下的网址规范对不上。

Ahrefs自己就栽过。他们把博客迁到新框架时,一条内链规则配错,全站内链都被加上了nofollow,等于告诉Google别理这些链接。文章里用了一个词形容:不太理想。连Ahrefs都会踩,小团队更没理由大意。

Ahrefs列了一张要统一的清单:

要统一的项建议
带不带www选一个,全站一致
尾斜杠选一个,和框架、托管平台的配置对齐
绝对地址还是相对地址选一个
HTTP还是HTTPS内链一律指向HTTPS
大小写通常用小写,比如/about-us/,别用/About-Us/
文件后缀倾向干净网址,比如/about/,别混用/about.html
连字符还是下划线倾向连字符,比如/seo-guide/
带参数的网址想清楚带sort=price这类参数的网址什么时候能链、什么时候规范化、什么时候避开
默认首页文件别同时出现/about/、/about/index.html和/about

最好在一个共享的链接组件或辅助函数里定义一次格式,别在全站各处手敲网址。然后爬一遍全站,找出指向重定向或者非规范版本的内链。用AI改站时,可以把这张清单直接写进给它的项目说明里,让它每次生成链接都照着来。

静态不等于快

静态站有快的名声,可静态生成本身不保证性能。一个静态站照样可能加载太多JavaScript、在每个页面都加载用不着的CSS、挂一堆沉重的第三方脚本、字体和图片加载方式不对、代码打包效率低。HTML是提前生成好了,渲染和交互照样会被这些拖慢。

AI做的站更要查。AI会不停地往里加脚本、库、动画和组件,不一定考虑它们叠加起来的性能代价。页面在预览里越改越精致,体积也越改越重。

Ahrefs的检查清单是:别在每个页面都加载或激活不需要的交互代码;把大包分成按需加载的小块;只有少数页面用的样式别全站加载,首屏可以考虑关键CSS;按每类页面的实际需要选静态生成、服务端渲染或其他渲染方式;压缩图片和字体,只预加载关键资源,删掉用不着的字重;非必要的第三方脚本移除或延后;静态资源要被缓存,并通过CDN分发。最后用PageSpeed Insights实测LCP、INP和CLS,别默认静态站就快。React和Next.js站的渲染模式怎么选,站里有一篇专门讲。

从WordPress迁到静态站要防什么?

从CMS迁到静态站,页面看起来一模一样,SEO照样可能出问题。迁移拿掉的不只是CMS的后台界面,还有重定向、站点地图规则、元数据逻辑、结构化数据、内链行为,以及其他原本在后台默默运行的SEO设置。

最大的风险是网址变了。旧网址消失又没有301重定向到新地址,指向它的外链和排名信号可能就丢了。WordPress常见的/2024/05/post-name/这类日期结构,迁到静态站后很容易被改成/blog/post-name/,一不留神就是几百个网址同时失效。另外,遗留的canonical、过时的站点地图条目、构建产物或缓存里残留的旧资源,也很容易漏掉。

Ahrefs建议把这次搬家当成一次完整的SEO迁移,别当成换个外观。上线前要做的事:

  1. 把每一个旧网址对应到它的新地址;
  2. 网址有变的地方,全部加301重定向;
  3. 对比新旧两边的canonical、元数据、结构化数据和站点地图规则;
  4. 确认重要的内链仍然指向正确的页面;
  5. 上线后测真实的线上站点,别只测预览或测试环境;
  6. 新旧两个版本都爬一遍,找出丢失的页面、重定向错误和其他意外变化。

静态站迁移完全可以做好,只是别指望新框架会自动把旧CMS默默做的事全部重建一遍。改版前后的完整防护,可以对照独立站改版不掉SEO的清单。

哪个静态框架对SEO更好?

Ahrefs的答案是:没有哪个框架天生“最适合SEO”。Astro、Next.js、Gatsby、Hugo、Jekyll都能做好SEO,区别在于你要做的工作量。canonical、Open Graph标签、结构化数据、站点地图规则、noindex处理,都要自己配,不能想当然。

差别比较明显的是图片处理,Astro这类框架的内置图片工具更强,有的框架把优化工作更多留给你。至于元数据、结构化数据、canonical和站点地图逻辑,差别主要在你配得好不好,选哪个框架倒在其次。所以别再问哪个框架最好,Ahrefs建议换成这几个问题:

  • 它能不能干净地实现你想要的网址结构?
  • canonical和元数据是怎么生成的?
  • 能不能控制noindex规则和站点地图排除?
  • 内置了哪些图片优化?
  • 加结构化数据、做验证方不方便?
  • 重定向、404和内链要多少手工活?

Pedro Dias的说法很实在:不是所有企业都需要CMS,也不是所有企业都离得开CMS。页面不多、更新不频繁的小站,很适合静态方案;工作流复杂的大型内容站,就不一定了。

放到外贸场景里,一个十几页的工厂官网,产品和公司介绍一年改不了几次,用静态站省心又快。一个每周发几篇博客、有好几个人编辑、还要做多语言的品牌站,没有后台的话,每次改内容都要找懂代码的人,SEO上省下的插件钱,可能全花在沟通上了。

常见问题解答

静态网站对SEO不利吗?

不会。静态站可以很快,代码也可以很干净。问题在于WordPress插件默认处理的canonical、站点地图、重定向、元数据、结构化数据和404,在静态站上要自己配置和检查。

静态站最常见的SEO问题有哪些?

Ahrefs总结了八类:尾斜杠和canonical冲突,站点地图、robots.txt与noindex不一致,图片没优化,模板生成的元数据和结构化数据出错,HTTP状态码不对,内链写法不统一,性能问题,以及从CMS迁移时丢失设置。

网址末尾带不带斜杠对SEO有影响吗?

带不带本身没有好坏,关键是全站统一。框架和托管平台默认不一致时,同一个页面可能在两个网址上都返回200,造成重复网址、多余跳转和排名信号分散。

Next.js的trailingSlash默认是什么?

默认会把带尾斜杠的网址重定向到不带的版本,比如/about/跳到/about。设成true后反过来,配合静态导出时/about会生成/about/index.html。

为什么404页面会返回200状态码?

常见原因是404没在框架或托管层正确配置,或者单页应用的兜底文件接住了所有未知路由。Josh Deltener记录的Nuxt加Vercel案例,就是生成的200.html兜底页面导致的,Google会把这种情况当成软404。

怎么检查网站的404是不是真404?

随手编几个肯定不存在的网址,用curl或浏览器开发者工具看真实的HTTP状态码,应该是404,页面长得像404不算数。

静态站的站点地图怎么排除noindex页面?

给不想进搜索的页面定一个统一标记,比如前置元数据里的noindex: true,让站点地图和RSS生成时都跳过带这个标记的页面。Jekyll的jekyll-sitemap支持sitemap: false,Astro的站点地图集成提供filter选项。

robots.txt能代替noindex吗?

不能。robots.txt控制的是抓取,不控制索引。被robots.txt挡住的网址仍可能因为外链被收录,想让页面不出现在搜索里要用noindex。

Astro、Next.js、Hugo哪个最适合SEO?

Ahrefs认为没有天生最适合SEO的静态框架。图片处理上Astro的内置工具较强,但元数据、结构化数据、canonical和站点地图逻辑,主要取决于你配置得好不好。

从WordPress迁到静态站要注意什么?

当成完整的SEO迁移来做:旧网址逐个对应新地址并做301重定向,对比新旧canonical、元数据、结构化数据和站点地图规则,上线后测真实站点,并把新旧两个版本都爬一遍找差异。

用AI生成的静态站要特别检查什么?

重点查模板生成的元数据和结构化数据是否和页面类型对得上,内链写法是否统一,以及AI不断加进去的脚本、库和动画有没有拖慢页面。可以把网址规范写进给AI的项目说明里。

权威参考资料

分享到
标签
版权声明

本文标题:《静态网站SEO常见的八类问题:Astro、Next.js、Hugo建站后要自己补上的那些活》

本文链接:https://zhangwenbao.com/static-site-seo-common-problems-astro-nextjs-hugo.html

版权声明:本文原创,转载与引用请注明作者与原文链接。许可协议: CC BY 4.0

继续阅读
发表评论
支持 Ctrl + Enter 提交