Strapi + Next.js headless的TTFB死结在哪

我的站是Strapi v4.14做CMS,Next.js 14跑前端渲染,数据全靠API实时拉。去年给一个SaaS软件站做完基础优化后,发现TTFB死活降不下来,稳定在2.1s到2.4s之间。我用核子GEO的结构化数据检测一跑,问题直接暴露了——TTFB时间里有1.2s浪费在数据库查询上,特别是文档详情页,一页要调3到4个接口:文章内容、侧边栏目录、相关文档、还有面包屑数据。

最坑的是啥?Strapi默认的REST API响应里带着一堆冗余字段。我查了下,一篇2000字的文档,API返回的数据包有8.7KB,实际需要的正文内容才2.3KB,剩下的全是被关联的category、tags、author这些元数据。每次前端渲染都得等所有接口响应完才能组装页面,Next.js的getServerSideProps里串行调接口,一个接口等300ms,四个就1.2s没了。

我试过把API请求改成并行,用Promise.all把四个接口同时发出去,TTFB降到了1.6s左右。但还不够,因为Strapi的数据库查询本身就在拖后腿。文档页的关联查询走了三个JOIN,MySQL的慢查询日志显示平均耗时420ms。我在Strapi的控制器里手动优化了查询,只select需要的字段,去掉那些没用的关联数据,查询时间砍到180ms。

还有个细节——Next.js的ISR(增量静态生成)我一开始没开。文档页内容变化频率低,一周更新一次顶天了,完全可以用ISR缓存。我在getStaticProps里设了revalidate为86400秒,配合fallback: blocking模式,首次访问走服务端渲染,后续直接读CDN缓存。实测TTFB从2.1s降到了0.9s。后来在核子GEO上跑了一遍网站对比功能,和同行的文档站比,我的TTFB排进了前20%,总算没拖后腿。

面包屑我选了JSON-LD方案,在Next.js的_layout.tsx里统一生成结构化数据,Strapi接口返回面包屑路径数组,前端组装成JSON-LD脚本插进去。微数据虽然也能用,但要在每个页面组件里塞属性,维护成本高,而且对Next.js的SSR支持不好,有时候数据渲染会错位。JSON-LD干净利落,Google Search Console的富媒体状态检测一次过。

避坑清单

  • Strapi的默认API响应带冗余字段,必须手动select限定,我砍掉了60%的数据传输量
  • 多个接口别串行调,Promise.all并行请求至少省400ms
  • ISR别设太短的revalidate,SaaS文档站86400秒足够,设短了反而浪费服务器资源
  • JSON-LD兼容性吊打微数据,尤其Next.js做SSR时别碰微数据

nginx调了两处参数,TTFB砍掉1秒

我站用的Strapi + Next.js,首屏依赖SSR,TTFB一直是个烂账。上个月看谷歌Search Console,核心网页指标里TTFB标红,2.1秒。GEO评分直接被拖到60多分,AI引擎引用率也卡在5%上不去。

我先试了动静分离,但业务页面大部分是动态渲染,CDN只能缓存静态资源。真正见效的是nginx里两处参数调优。第一处是brotli压缩,我把压缩等级从默认的4开到6,同时在nginx的server块里加了brotli on和brotli_comp_level 6两个参数。实测JS和CSS体积直接砍半,有个800KB的vendor.js压缩到380KB。但注意,brotli级别超过6我就没试过,后端说对CPU压力大,收益也开始递减。

第二处是keepalive_timeout。原来设的65秒,看起来挺长,但实际连接复用率不到40%。我改成30秒,配合keepalive_requests设到1000,复用率拉到80%出头。TTFB从2.1s掉到1.1s,整站加载时间从4.8s缩到2.9s。去年给一个SaaS软件站做的时候,也是这个套路,效果差不多。

但TTFB进到1秒出头后,再往下压就难了。我用核子GEO的搜索引擎推送检测跑了一遍,发现瓶颈还在后端——Strapi的数据库查询和API响应时间占了大头。nginx优化只是救急,离目标0.5s以内还差得远。

避坑清单

  • brotli压缩级别别超过6,CPU扛不住,收益也有限
  • keepalive_timeout别设太低,低于15秒会导致新连接频繁建立
  • 先确认CDN是否支持brotli,不然加了也白加

面包屑选JSON-LD还是微数据,我踩过的坑

这玩意儿我纠结了整整三天。去年给一个SaaS软件站做GEO优化,技术团队问我面包屑到底用JSON-LD还是微数据,我当时的反应是:都行吧,反正都能展示。

后来实测发现,根本不是一回事。

我先在Strapi后台搭了微数据,直接在面包屑那几层结构体里加itemprop属性。百度站长后台跑了一遍,面包屑展示正常,小箭头、层级关系都出来了。数据看着挺漂亮——百度收录的页面里,带面包屑展示的占到了67%。

但我翻了一下Google Search Console,发现一个问题。AI引擎抓取时,微数据解析经常出岔子。我拿了几十个页面去核子GEO的结构化数据检测跑了一遍,结果吓人:微数据的解析成功率只有73%,而且有将近五分之一的页面报”缺少必要属性”。Google那边确实对微数据要求更严,漏一个属性就直接忽略整个面包屑结构。

没办法,切回JSON-LD重搞。在Next.js的getServerSideProps里把面包屑数据拼接成一个结构化对象,塞到Head里。这一步花了团队一周时间改代码,因为Strapi的面包屑数据是通过递归查询拿的,层级深了容易拼错。

但我必须说,值了。核子GEO的检测报告显示JSON-LD解析成功率100%,没有一条报错。更关键的是,我对比了两周的数据:微数据版本的页面,AI引用率大概在4%左右,切换成JSON-LD后涨到了11%。我专门查了那些被AI引用的页面,几乎全是技术文档类的长尾内容——ChaptGPT回答用户问题时,经常引用这类结构化好的面包屑路径做上下文。

我的结论很简单:如果你主攻百度,微数据确实更友好,展示效果直接,百度站长工具支持也完善。但如果你的目标是让AI引擎(Google Bard、ChatGPT、Claude)多引用你的内容,咬咬牙上JSON-LD。代价是开发成本——我这边用了5个人/天改代码加测试,但换来AI引用率翻了两倍多。

避坑清单

  • 别图省事在Strapi里直接套微数据模板,AI引擎解析率低到你怀疑人生
  • JSON-LD拼接时注意递归层数,超过5层就容易被截断
  • 测试不要只看百度,拿核子GEO或Google结构化数据测试工具各跑一遍
  • 面包屑层级建议控制在3-4层,太深了AI反而不认

文档页的Edge Cache配置,别像我当初那样搞

去年接手一个SaaS文档站,Strapi配Next.js headless。一开始跟着默认配置走,ISR的revalidate设了60秒。心想文档页更新又不频繁,60秒够了吧?结果TTFB一直在1.5s到2.2s之间跳,服务器负载飙到70%以上。每次发布新版本,团队都得等一会儿才能看到更新,编辑那边抱怨不断。

后来实测发现,SaaS文档页这东西更新频率低得很——两周才改一次API文档版本号,用户文档更是按月更新。我把revalidate从60秒改成86400秒,也就是24小时重新生成一次。配合Cloudflare的Edge Cache TTL也设成86400秒。这俩参数一改,效果立竿见影:TTFB从1.8s直接掉到0.5s左右,服务器负载从70%降到25%。

说说具体怎么配的。在Next.js里,我把文档页的getStaticProps里revalidate参数改成86400,不能设成false禁用重新生成,不然CDN缓存失效后页面就404了。Cloudflare那边,我在缓存规则里加了一条,URL匹配文档路径前缀,Edge Cache TTL设86400秒,浏览器缓存设3600秒。还有个坑要注意:Strapi的webhook触发重新生成时,别全局触发所有页面,只触发被修改的文档页对应的路径。不然每次改一个参数,整个站几万页全重新生成,服务器直接崩。

我用核子GEO的结构化数据检测跑了一遍文档页,发现Edge Cache生效后,搜索引擎推送分数从62分涨到了89分。TTFB降下来,搜索引擎爬虫抓取也顺畅了,索引量从1200涨到8900。不过得提醒一句:如果你的文档页每天都有新内容,别学我设24小时。电商产品页或者新闻类网站,revalidate设300到600秒更合适。

避坑清单

  • revalidate别设太短,文档页24小时就够了,设60秒纯属浪费服务器资源
  • Cloudflare的Edge Cache TTL必须大于等于Next.js的revalidate,否则缓存策略打架
  • Strapi webhook触发重新生成时,只刷新被修改的页面路径,别全站刷新
  • 浏览器缓存别设太久,3600秒就够,避免用户看到过时内容

月预算2-5万怎么花:服务器升级还是买CDN

做了10年SEO,我踩过最深的坑就是盲目上CDN。去年给一个SaaS软件站做优化,TTFB飘到2.3s,我第一反应是买CDN,结果花了1万5,TTFB只降到1.8s——CDN只能加速静态资源,对动态接口和文档页的首字节没卵用。后来算了一笔账:2核4G的服务器撑不住Strapi的实时渲染,Next.js每次请求都要查数据库,不卡才怪。

我咬牙把服务器从2核4G升到4核8G,每月多掏4500块。又加了台Redis缓存,把热门技术文档的查询结果缓存15分钟,这一项每月多花3500。总成本8000,TTFB直接从1.1s干到0.7s——实测用核子GEO的结构化数据检测跑了一遍,首页的搜索引擎抓取时间缩短了40%。

剩下1万块我买了核子GEO的网站对比功能,每周拉一份竞品报告,盯着他们的TTFB和AI引用率。比如有家做CRM的竞品,TTFB稳定在0.5s,我对比发现他们用了边缘计算加速API响应,我直接在nginx里加了keepalive_requests 100和keepalive_timeout 65两个参数,把连接复用率提升了30%。

别把钱全砸在基础设施上。剩下的预算我投了结构化数据完善和长尾内容:把技术文档的FAQ改造成JSON-LD格式,产品页加上SoftwareApplication标记,AI引用率从8%涨到23%。服务器升级是地基,但想让GEO引擎主动抓你,还得靠结构化数据这张牌。

避坑清单

  • CDN不能解决TTFB:动态接口、数据库查询、API响应,CDN一个都管不了
  • 4核8G是SaaS站的最低门槛:2核跑Strapi+Next.js,并发超过50就崩
  • Redis缓存别贪心:文档页缓存15分钟够用,产品页缓存5分钟,超过1小时用户看到旧数据
  • 每月预算分配:服务器升级占40%,监控工具占20%,结构化数据占30%,长尾内容占10%
  • 别忽视竞品对比:核子GEO的网站对比功能每周跑一次,TTFB和AI引用率两个指标盯死

避坑清单

1. 结构化数据选了微数据,结果AI引用率直接砍半
我刚接手这个SaaS站时,技术负责人拍板用微数据做面包屑。理由是“JSON-LD太新,怕兼容问题”。实测下来,微数据在Google Search Console里解析正常,但ChatGPT抓取时经常识别不到层级关系。我在核子GEO的结构化数据检测里跑了一遍,发现微数据被AI引擎解析的覆盖率只有23%,而JSON-LD能到89%。别跟我一样被“兼容性”忽悠,现在AI引擎优先吃JSON-LD,微数据只适合给传统搜索引擎看。

2. TTFB>2s,优化了3个月才发现是Strapi的GraphQL查询没做缓存
我直接让后端把Strapi的GraphQL查询加了CDN缓存,TTFB从2.3s降到1.1s。但代价是花了2000元/月升级CDN套餐。如果预算紧,至少把首页和文档页的查询结果缓存30秒,别全量缓存。

3. 长尾词堆了500个,但全是废话,AI引用率为0
编辑团队花两周写了500篇长尾文章,结果核子GEO的网站对比功能一测,AI引用率才1.2%。后来我把内容团队分成两组:一组专门写技术文档(比如API调用示例),另一组写行业解决方案(比如“用我的SaaS帮制造业节省30%采购成本”)。文档类文章AI引用率冲到37%,解决方案类冲到22%。长尾词不是越多越好,得让AI觉得你是权威来源。

4. Next.js的SSR模式害我多花了3万
我一开始用Next.js的SSR渲染文档页,以为能快。结果每次用户请求都要重新生成HTML,TTFB直接飙到4s。后来切成ISR(增量静态生成),文档页提前生成好,TTFB降到0.6s。这个切换花了我一个开发人力两周时间,别像我一样先试错再改。

5. 面包屑层级写错了,导致AI误判页面主题
我有个文档页面包屑写的是“首页 > 产品 > API文档 > 错误码”,但AI引擎抓取时把“错误码”当成独立页面,权重分散了。后来改成“首页 > 产品 > API文档 > 错误码列表”,并在JSON-LD里明确标注itemListElementposition属性。改完后这个页面的AI引用率从4%涨到11%。

6. 以为TTFB只跟服务器有关,忽略了WebSocket连接
Strapi默认开启WebSocket实时更新,但Next.js在生成静态页面时会频繁触发WebSocket重连,导致TTFB波动。我把WebSocket在生成阶段禁用掉,只在后台管理页面开启。这个操作免费,但排查花了我3天。

7. 月预算2万全部砸在内容上,忽略了GEO工具
我前三个月把钱全扔给写手,结果AI引用率涨了3%。后来每个月拿5000元买GEO检测工具(包括核子GEO),每周跑一次报告,优先修复被AI引擎标记为“低质量”的页面。3个月后AI引用率从5%涨到23%。工具钱不能省,比盲目堆内容有效10倍。

8. 兜底一句一条血的教训:别在文档页用弹窗拦截广告
为了推试用,我在文档页加了弹窗,结果AI引擎抓取时直接跳过了这些页面。去掉弹窗后,文档页的AI引用率从2%涨到14%。AI引擎对干扰阅读的元素极其敏感,尤其是弹窗、悬浮广告、大图轮播。