Prismic 优化检测 免费在线检测工具
首页笔记 › 网站为什么拿不到 Lighthouse 满分?我改过的 6 类常见问题

网站为什么拿不到 Lighthouse 满分?我改过的 6 类常见问题

作者:Cody Wang | 前端工程师,做 Prismic / SvelteKit / Next.js 网站的开发与性能优化

先说清楚:这篇不讲玄学,只列我实际改过的、最常见的 6 类问题。每一条都告诉你:为什么会这样Google 官方怎么说(附链接)→ 我改过的真实数字怎么改。看完你至少能自己排查掉一半。


#1. 图片:三个最容易忽略的地方(alt / 尺寸 / 体积)

alt 是写给人(和机器)读的

Lighthouse 提示 Image elements do not have [alt] attributes 时,很多人会随手补个 alt="图片" —— 那等于没写。屏幕阅读器读图靠它,图片加载失败时用户也靠它知道那是什么。

  • alt="车库门 车库门安装 新西兰车库门"(堆关键词,读起来很怪)
  • alt="深灰色钢制车库门安装完成后,从街道看向车道"
  • 纯装饰性图片:写 alt=""(空字符串,不是省略)
  • CMS 站要点:内容是编辑上传的,模板层必须兜底 alt={image.alt || 上下文兜底}

📎 Google 官方:web.dev · Accessible images 📊 我改过的:一个官网 32 张图alt0 张

② 不写 width / height,页面加载时会"跳一下"

浏览器不知道图片要占多大地方,只能先排别的元素;图下载完再重排 —— 用户看到内容位移,这就是 CLS。

<img src="/hero.webp" width="1200" height="630" alt="…" />
<!-- 或用 CSS:aspect-ratio: 16 / 10; -->

📎 Google 官方:web.dev · Optimize CLS

③ 体积:格式、尺寸、体积是三件事

设计稿导出的 PNG 直接上传,一张首页横幅就可能 527 KB;一个星标 SVG 能到 123 KB(它本该 2 KB)。

  • WebP / AVIF
  • 按显示尺寸给图(400px 宽的卡片别给 2000px 的图);
  • 用 CDN 参数自动做:?auto=format,compress&q=75&w=800auto=format 会给支持的浏览器自动发 WebP);
  • 首屏图不要 loading="lazy",要 fetchpriority="high";非首屏用 loading="lazy"

📎 Google 官方:Lighthouse · Serve images in modern formats 📊 我改过的:静态资源 996 KB → 79 KB


#2. 字体:不是"用好字体",是"别一次加载全部"

现象:手机上文字"先空白一秒再出现",LCP 被拖慢。

为什么:很多站把整个字体家族一次加载(4–6 个字重、还带全角字符);字体没到之前浏览器可能不显示文字(FOIT)。

怎么改

  • 只用真正用到的字重(比如 400 / 600);
  • 只保留需要的字符集(woff2 + unicode-range 分片 —— 中文尤其重要:是拉丁文的页面就不该加载中文字体);
  • font-display: swap

📎 Google 官方:Lighthouse · Ensure text remains visible during webfont load 📊 我改过的:Roboto 468 KB + Raleway 309 KB57 KB + 43.7 KB(合计 419 KB → 100.7 KB)。


#3. 第三方脚本:不是"要不要删",而是"什么时候加载"

现象:总阻塞时间(TBT)几百毫秒甚至 1 秒以上,滚动卡、点击没反应。

为什么:GTM、Facebook Pixel、客服插件这些通常是同步 JS,会和你的页面抢主线程;主线程被占住时,用户点击就是没反应。

怎么改:把加载推到页面空闲或首次交互之后

['scroll','click','keydown','mousemove','touchstart']
  .forEach(e => addEventListener(e, loadTags, { once: true, passive: true }));
requestIdleCallback?.(loadTags);          // 或
setTimeout(loadTags, 3500);               // 兜底

⚠️ 一个现实的边界:很多公司的追踪脚本是业务要求,不能删。那就只改"加载时机",别改"有没有" —— 这是能谈的、也是有效的。

📎 Google 官方:Lighthouse · Third-party summaryweb.dev · TBT 📊 我改过的:TBT 284 ms → 179 ms,只是改了注入时机。


#4. 导航和按钮是 JS 点击,不是真正的链接

现象:SEO 提示 Links are not crawlable,新页面收录很慢。

为什么:爬虫只认 <a href="...">。用 <button on:click={() => scrollTo('#x')}> 做的导航,在爬虫眼里根本不是链接——你站内最重要的入口,搜索引擘看不到。

怎么改

<a href="/#whatwedo">我们做什么</a>
<!-- 需要平滑滚动?用 CSS:html { scroll-behavior: smooth },不要用 JS 拦截点击 -->

📎 Google 官方:Google Search Central · Links are crawlable 📊 我改过的:一个站全站只有 4 个真 <a href>,其余全是 JS 滚动;改成真链接(样式不变)后 SEO 83 → 100


#5. canonical 和结构化数据:让搜索引擎知道"以哪个为准"

为什么

  • canonical 告诉搜索引擎"同一内容以哪个 URL 为准" —— 带参数、多语言、有 staging 的站尤其容易出重复内容问题;
  • 结构化数据(JSON-LD) 让搜索结果显示评分、服务范围这些"增强"信息。
<link rel="canonical" href="https://example.com/page" />
<meta property="og:url" content="https://example.com/page" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"ProfessionalService","name":"…"}
</script>

⚠️ 我踩过的坑:在 Svelte 里写 <script type="application/ld+json">{JSON.stringify(data)}</script>,页面会把它原样输出成字符串(用户真能在页面上看到 {JSON.stringify(data)})。必须用 {@html ...}我是在 Facebook Pixel 报 "Malformed JSON" 时才发现的 —— 所以发布后一定要在浏览器里看一眼渲染结果。

📎 Google 官方:CanonicalStructured data


#6. 对比度和触摸目标:可访问性最后那几分

现象:可访问性 97/98 上不去,报 color-contrasttarget-size

为什么

  • 浅灰字在白底上"看着高级",但对比度不够 —— WCAG AA 要求 4.5:1(大字号 3:1);
  • 手机上可点目标至少要 24×24 px,挨太近也会被判不合格。

怎么改:别凭眼睛判断,跑一次 Lighthouse 让它告诉你具体色值;可读性优先于"高级灰"。

📎 官方:web.dev · Color contrastW3C · Target Size 📊 我改过的:#a4a4a4#f7f7f7 上只有 2.85:1(不达标)→ 改成 #7676764.54:1,达标);页脚链接 85×20 px → 加内边距到 ≥24 px 高。


#最后

满分不是目的 —— "用户 3 秒内看到内容、点得动、搜得到"才是目的。但 Lighthouse 的好处是:它把"用户感受"翻译成可验证的数字,让你能一条条改、一条条验收。

上面这 6 类,我自己最多的一次是改了 8 轮才把移动端从 61 分推到 86 分(在必须保留第三方追踪脚本的前提下)。大多数站点不用改 8 轮 —— 前 3 条就能省掉一半体积。

你的站卡在哪个分数? 把网址发我,我用自己写的检测工具给你跑一份免费诊断:告诉你分数为什么上不去、哪几条能改、哪几条是第三方脚本的"数学上限"、改了也没用。

(工具在这里:prismicaudit.com —— 59 个技术栈探测器 + 性能 / 图片 / SEO / 可访问性体检,桌面版 Lighthouse 四项 100/100/100/100。)