静态网站SEO常见的八类问题:Astro、Next.js、Hugo建站后要自己补上的那些活
本文目录
- 静态站的SEO问题都是从哪冒出来的?
- AI写的站,问题藏得更深
- 尾斜杠和canonical为什么会打架?
- 两个框架的默认值就不一样
- 怎么修
- 站点地图、robots.txt和noindex怎么保持一致?
- robots.txt可能压根没有
- 用一个标记管住所有出口
- 图片和模板,一错就是一大片
- 图片绕开了优化流程
- 模板里的默认值会复制到每一页
- 页面写着404,服务器说200
- 原因出在单页应用的兜底文件
- 用不存在的网址去试
- 内链写法和性能,AI最容易越改越乱
- 同一个页面,五种链接写法
- 静态不等于快
- 从WordPress迁到静态站要防什么?
- 哪个静态框架对SEO更好?
- 常见问题解答
- 静态网站对SEO不利吗?
- 静态站最常见的SEO问题有哪些?
- 网址末尾带不带斜杠对SEO有影响吗?
- Next.js的trailingSlash默认是什么?
- 为什么404页面会返回200状态码?
- 怎么检查网站的404是不是真404?
- 静态站的站点地图怎么排除noindex页面?
- robots.txt能代替noindex吗?
- Astro、Next.js、Hugo哪个最适合SEO?
- 从WordPress迁到静态站要注意什么?
- 用AI生成的静态站要特别检查什么?
- 权威参考资料
摘要:用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.js | next.config.js里的trailingSlash | 默认会把带尾斜杠的网址重定向到不带的,比如/about/跳到/about;设成true就反过来,配合静态导出时/about会生成/about/index.html,默认生成的是/about.html |
| Astro | astro.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迁移,别当成换个外观。上线前要做的事:
- 把每一个旧网址对应到它的新地址;
- 网址有变的地方,全部加301重定向;
- 对比新旧两边的canonical、元数据、结构化数据和站点地图规则;
- 确认重要的内链仍然指向正确的页面;
- 上线后测真实的线上站点,别只测预览或测试环境;
- 新旧两个版本都爬一遍,找出丢失的页面、重定向错误和其他意外变化。
静态站迁移完全可以做好,只是别指望新框架会自动把旧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