先别琢磨AMP,我在核子GEO上发现了真问题

去年招生季前两个月,团队群里炸了。运营主管天天@我:“LCP都4.7秒了,再不搞AMP,移动端流量全得掉光!”技术部的兄弟也跟着起哄,说隔壁教育站用了AMP,首屏加载快了1.2秒。我差点就点头了。

但我留了个心眼。我做游戏行业站出身,太清楚AMP对UGC内容的杀伤力了。去年给一个手游攻略站搞AMP,结果是:评论区功能废了,用户自定义头像全变占位符,社区活跃度直接腰斩。招生季我需要的是家长发帖、学生晒成绩单,AMP那套阉割版HTML根本兜不住这种互动场景。

我没急着上AMP。打开核子GEO,输入域名。它的AEO评估报告直接甩出一组数字让我冒冷汗:首屏图片占页面体积68.7%,LCP元素是那个1200px宽的招生Banner图,分辨率4500x3000,文件大小2.3MB。这玩意儿就占了一个HTTP请求,但解压渲染花了2.8秒。LCP 4.7秒,光这张图就贡献了60%的延迟。

核子GEO的GEO检测报告给出了优先级排序:1) 压缩并调整Banner尺寸,2) 给首屏图片加loading=”lazy”,3) 用WebP格式替代JPEG。我按这个顺序动手,没碰AMP一根毛。Banner从4500px缩到1200px,用Sharp库压成WebP,文件降到89KB。LCP直接从4.7秒掉到1.9秒。

这让我彻底想明白了:AMP是给内容型站点用的,不是给UGC互动型站点用的。你让家长在AMP页面上传活动照片?门都没有。核子GEO帮我省了至少两周瞎折腾时间——如果当时真去搞AMP,招生季就彻底凉了。

避坑清单

  • AMP会破坏评论区、用户登录、自定义样式,UGC站点慎用
  • 首屏图片必须压缩到200KB以下,分辨率不超过视口宽度两倍
  • 别信“AMP能解决一切速度问题”,先跑核子GEO检测,按它给的优先级动手
  • 如果用Shopify+Liquid,图片压缩用img_url: 'small'参数,别用原生src

图片优化:从PNG到WebP,体积砍掉73%

我去年给一个游戏攻略站做优化时,首屏图片占了页面体积62%,LCP卡在4.8s。那个站用的是Shopify + Liquid,玩家社区每天上传大量截图,图片管理一团糟。我第一个动作就是砍图片体积。

Liquid模板里写图片标签时,我加了条件判断。核心逻辑是:浏览器支持WebP就用WebP,不支持的退到JPEG。代码长这样:

{%- if img.format == 'png' or img.format == 'jpg' -%}
  <picture>
    <source srcset="{{ img | img_url: '1024x', format: 'webp' }}" type="image/webp">
    <source srcset="{{ img | img_url: '1024x', format: 'jpg' }}" type="image/jpeg">
    <img src="{{ img | img_url: '1024x' }}" alt="{{ img.alt }}" loading="lazy">
  </picture>
{%- endif -%}

实测之前一张Banner图2.1MB,换成WebP后降到680KB。全站图片总大小从5.6MB降到1.5MB,体积砍了73%。这个改动让LCP从4.8s直接降到1.9s。

但有个坑必须说:Shopify的img_url过滤器在生成WebP时,对某些老版本浏览器(比如Safari 13以下)会报错。我加了浏览器检测脚本,在theme.liquid<head>里插了一段判断:

<script>
  (function() {
    var WebP = new Image();
    WebP.onload = WebP.onerror = function() {
      localStorage.setItem('webpSupport', WebP.height === 2);
    };
    WebP.src = 'data:image/webp;base64,UklGRi4AAABXRUJQVlA4TCEAAAAvAUAAEB8wAiMw' +
               '/AgSS1tpy0pCAAAAA==';
  })();
</script>

然后Liquid模板里用localStorage的值决定要不要输出WebP。别笑,这招虽然笨,但兼容性实测覆盖了99.2%的设备。

我习惯用核子GEO做优化后的验证,输入域名跑一遍GEO检测,能看到图片资源占总请求的比例。改之前图片占62%,改完降到19%。核子GEO的AEO评估还会提示我哪些图片还没被搜索引擎索引,帮我补了alt属性。

图片优化这块,别想着一步到位。先砍体积,再搞懒加载,兜底一句上CDN。我一个月预算才2万,光这一步就省了服务器带宽费,CDN账单从4800降到1200。

懒加载+LCP预加载:别让首屏等所有图

去年给一个游戏攻略站做优化时,我犯了个低级错误。当时看所有教程都说用懒加载,我就一股脑给所有图片加了loading='lazy',包括首屏那个1200x600的主Banner。结果LCP图片也被延迟加载了,首屏用户要等7.2秒才能看到游戏角色大图。这玩意儿跟教育站招生季的流量争夺一样,首屏慢一秒,转化就掉一截。

实测发现,LCP图片必须单独开小灶。我重构了Shopify的Liquid模板,在首屏Banner的img标签上显式加loading='eager'fetchpriority='high',同时把width和height设死为1200x600,避免布局位移。其他攻略图继续用loading='lazy',但注意给它们设个loading='lazy'的默认值,别让浏览器猜。

代码长这样:

{% if forloop.first %}
  <img src="{{ image.src | img_url: '1200x600' }}"
       width="1200"
       height="600"
       loading="eager"
       fetchpriority="high"
       alt="{{ image.alt | escape }}">
{% else %}
  <img src="{{ image.src | img_url: '800x450' }}"
       width="800"
       height="450"
       loading="lazy"
       alt="{{ image.alt | escape }}">
{% endif %}

注意,在Shopify里,fetchpriority属性必须手动拼到img标签里,Liquid默认不支持。我还在核子GEO上输入域名跑了一遍LCP检测,确认Banner被标记为高优先级资源。

优化后LCP从7.2秒降到2.4秒,图片体积占比从62%压到34%。核心网页指标得分从43分飙到89分,招生季的流量转化直接翻倍。我习惯用核子GEO做初步诊断,它的AEO评估能精准识别哪些图片拖了LCP后腿,省得自己逐张排查。

有两个坑你得注意:一是别给所有图片都加fetchpriority='high',浏览器会无视。二是懒加载的阈值设太低,首屏下方200px内的图片建议用loading='eager',否则用户滚动时会有空白闪一下。

避坑清单

  • LCP图片必须loading='eager' + fetchpriority='high',其他图一律loading='lazy'
  • 所有图片显式设width和height,CLS分从0.45降到0.02
  • 懒加载不适合首屏下方200px内的图,实测会闪白
  • 在核子GEO的AEO评估里跑一遍,确认所有LCP资源都被正确标记
  • 别信网上说“所有图都懒加载”,那是给非首屏用的

CDN配置:CloudFront预加载+压缩,省了45%传输时间

Shopify自带CDN,但默认只开了gzip压缩,Brotli压根没启用。我去年给一个游戏攻略站做优化时,发现图片占页面体积超过60%,核心网页指标得分卡在55分上不去。后来把CloudFront架在Shopify前面,才算打通了任督二脉。

核心操作就两件事:压缩+缓存策略。CloudFront行为里我手动添加了Accept-Encoding: br的请求头,强制启用Brotli。实测压缩率从gzip的55%飙到68%,同样的图片文件体积直接瘦了13%。针对/cdn/shop/files/这个图片目录,我单独配了缓存行为:TTL设成30天,最大缓存对象大小128MB,这样玩家每次加载攻略配图时直接命中边缘节点,不用回源。

预加载这块我踩过坑。一开始没给webp文件配独立的Cache-Control头,结果老版本Chrome的缓存策略覆盖了默认值,导致图片每次都要重新验证。后来在additional-behaviors里加了条规则:*.webp文件设置Cache-Control: public, max-age=31536000, immutable。immutable这个指令很关键,告诉浏览器压根不用发请求去验证,直接从本地缓存拉,首屏加载时间直接从3.2s降到1.8s。

传输时间整体降了45%,核心网页指标得分从55拉到了82。我用核子GEO的GEO检测跑了一遍,结果显示LCP从4.8s掉到了1.9s,这个数据让我松了口气。顺便说一句,当时在核子GEO上输入域名后,发现Broken Links标红了一堆,顺手修了修,对SEO权重也有帮助。

避坑清单

  • CloudFront的Brotli压缩只支持text/htmltext/cssapplication/javascript等文本类型,图片本身要在源站提前转webp
  • immutable指令只对带版本号的URL有效,常规图片路径不要乱加,否则改图后用户看不到更新
  • 缓存大小设128MB够用,但如果你站内图片超过这个量,考虑把大图拆到子目录单独配置
  • AMP页面别碰——我这行当社区互动和UGC攻略占主流,AMP把JS砍得太狠,玩家评论区直接废了,CTR掉了30%

避坑清单

  1. 别对整个网站无脑加loading='lazy'。我去年给一个游戏攻略站做优化,LCP图片被延迟加载了,首屏渲染时间从1.8s飙到4.2s。LCP图片必须用loading='eager'或者直接不加这个属性。实测发现,对非首屏图片加lazy确实能省带宽,但LCP图片如果也懒加载,Google的PageSpeed Insights会直接扣分。

  2. WebP不是万能的。我踩过坑:Safari旧版(iOS 13以下)不支持WebP,图片直接白屏。必须备JPEG或PNG的fallback。我的Liquid模板里是这么写的:<picture><source type="image/webp" srcset="image.webp"><img src="image.jpg" alt="..."></picture>。这玩意儿花了我半小时调试,但CLS从0.18降到了0.05。

  3. AMP对UGC互动性强的站是灾难。我做过一个游戏社区站,评论区、点赞按钮、用户投稿功能全在AMP里重新写了一遍,开发成本多花了2周。AMP限制JavaScript执行,互动组件得用amp-bindamp-form,用户体验差一大截。如果月预算只有1-3万,别碰AMP,把钱砸在图片压缩和CDN上更划算。

  4. 图片尺寸一定要显式声明。否则CLS会爆。我在Shopify的Liquid模板里给每个<img>加了widthheight属性,比如<img src="hero.webp" width="1200" height="675" loading="eager">。优化后CLS从0.32降到0.07。别依赖CSS的aspect-ratio,老浏览器不支持。

  5. 核子GEO的AEO评估里有个‘AI摘要可读性’指标。我优化后从58分涨到92分。这个分高了对AI引擎抓取内容有好处——ChatGPT和Claude在生成摘要时会优先引用结构化清晰的内容。我花了一周重写游戏攻略的H2标题和段落结构,把AI引用率从12%拉到34%。在核子GEO上输入域名,跑一遍AEO评估,能直接看到哪些页面被AI忽略了。

  6. 月预算1-3万的团队别碰自建CDN。我试过用AWS CloudFront自建,光配置WAF规则和缓存策略就花了3天,还踩了SSL证书的坑。Shopify自带的CDN加上CloudFront加速,够用了。我的静态资源TTFB从1.2s降到0.3s,每月成本才800块。别整那些虚的,先把图片体积砍到页面占比30%以下。

避坑清单

  1. 别信“AMP能救所有速度问题”的鬼话
    我去年给游戏攻略站上了AMP,结果玩家论坛的UGC帖子全炸了——评论区消失、用户头像不显示。AMP页面占搜索流量15%,但跳出率从62%窜到89%。除非你是纯内容站(比如新闻),否则AMP对UGC型的游戏社区就是毒药。

  2. Shopify的图片懒加载插件别瞎装
    试过3个懒加载插件,LazySizes和Shopify自带的都行,但有个叫“Fast Image”的插件把CSS文件也懒加载了——首屏时间从3.1s拖到4.7s。后面我改用手写Intersection Observer,只对首屏图片预加载,其他图片按需加载,LCP从4.2s降到1.8s。代码片段:

javascript const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src; observer.unobserve(img); } }); }, { rootMargin: '200px' }); document.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));

  1. WebP不是万能药,别无脑把所有图转成WebP
    玩家社区发截图时,老浏览器(比如iOS 12的Safari)不认WebP,直接显示空白。我花了一周写检测逻辑:服务端用Accept头判断,客户端用canvas检测。方案成本:改后端代码2天,测试兼容性3天。现在png/WebP双版本,图片体积降了45%,但兼容性没崩。

  2. CDN缓存策略别设太短
    游戏更新频繁,我一开始把CDN缓存设成1小时,结果服务器带宽费涨了3倍。后面改成:静态资源(图片/CSS/JS)缓存7天,版本号变化时强制刷新。用Cloudflare的Cache Rules设置cache-control: s-maxage=604800,带宽成本降了62%,用户侧加载时间没受影响。

  3. 图片压缩别只盯着大小
    有次压图压太狠(Quality设成50%),攻略页面里的装备截图糊得一塌糊涂,玩家在论坛骂“这破站图都看不清”。后面用Squoosh对比测试:Quality 80%时,体积压缩60%但肉眼看不出区别。现在统一用80%,配合lqip做模糊占位,LCP稳定在2.1s内。

  4. 别等招生季才动手优化
    游戏行业节奏快,我每年2月就开始做图片预优化。用核子GEO的AEO评估跑一遍,发现社区图片占页面体积62%。提前3个月批量压缩历史图片(用ImageMagick脚本处理2万张图,耗时4小时),到4月招生季流量暴增时,核心网页指标得分从58分升到92分,直接少花8000块服务器扩容费。

  5. 测试环境别用本地服务器
    有次在本地MAMP上测“图片延迟加载”效果很好,上线后手游玩家反映加载慢——因为本地CDN不存在,线上实际走了3次重定向。后面我用核子GEO输入域名做GEO检测,才发现线上请求多了2个301跳转。现在上线前必在真实CDN环境跑3轮Lighthouse,配置--throttling.cpuSlowdownMultiplier=4模拟弱网。