← 返回博客

前端性能优化实战:从 Lighthouse 50 到 100 的工程方法

性能优化不是"压到多少分就交差",而是理解每一分从哪来、代价多大。本文从本站的优化过程出发,拆解九项优化手段:图片格式、构建产物分析、字体加载、CSS/JS 分层策略。附优化前后的 Lighthouse 对比数据。【点击查看九项优化手段】

先说结论:性能优化是投资,不是成本

本站从最初版本到现在的 Lighthouse 100/100/100,不是靠某一次”优化大招”达成的,而是一步步加出来的。每次加的代价都很小,但积累起来效果明显。

本文不讲理论,只说我在本站实际做的九件事,每件都附带优化前后的数据。


1. 图片格式升级:PNG → WebP

这是性价比最高的优化。本站所有图片从 PNG 转为 WebP:

图片原 PNGWebP缩减
OG 默认图154 KB10 KB93%
Logo172 KB14 KB92%
微信二维码156 KB30 KB81%
苹果图标32 KB4.5 KB86%

四张图从 514 KB 降到 58 KB,减少了 89%。而且 WebP 是浏览器原生支持的,没有兼容性问题(不支持的场景极少,可以做 回退)。

如果你只做一件事,就做这个。


2. 构建产物分析:知道东西去哪了

优化之前先要知道问题在哪。我用 astro build 之后检查 dist/ 目录:

dist/
  _astro/
    index.12345.js    87 KB
    style.67890.css   23 KB

87 KB 的 JS 对于纯内容站来说太大了。分析发现是一些第三方库被打包进去了。解决方案:

  • 把只在特定页面使用的组件做动态导入
  • 内联 SVG 图标(替代外部的图标库)
  • 移除未使用的 CSS(Tailwind 的 purge 默认开启,但需要确认配置正确)

优化后 JS 降到 0 KB(首页完全不需要 JS),CSS 降到 12 KB。


3. 零 JavaScript 默认

本站是 Astro 静态站,默认行为是”发零 JS 到客户端”。这是 Astro 和 Next.js 的核心区别——Astro 在构建时把所有页面渲染成静态 HTML,浏览器不需要执行任何 JavaScript 就能看到完整内容。

这带来的好处:

  • LCP 1.7s(首屏内容加载时间)
  • TBT 0ms(总阻塞时间,因为没有 JS 需要执行)
  • CLS 0(页面从开始到结束没有布局偏移,因为所有元素在 HTML 里就有确定尺寸)

如果你的站点也是内容为主的,选择一个默认零 JS 的框架是最省力的性能优化。


4. 字体加载优化

本站用了 Inter 字体作为正文字体,但没让它阻塞渲染:

@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter.woff2') format('woff2');
  font-display: swap;  /* 关键:先用系统字体渲染,WebFont 加载后再替换 */
  font-weight: 400 600;
}

font-display: swap 的意思是:浏览器先用系统字体渲染文字,等 WebFont 下载完成后替换成设计字体。用户不会看到空白文字,只会看到”字体闪了一下”(FOUT),比”白屏等字体”(FOIT)好得多。


5. CSS 分层策略

Tailwind 生成的 CSS 文件大小和你的 HTML 模板数量成正比。为了控制 CSS 体积:

  • 只使用 Tailwind 的工具类,不写自定义 CSS(除了少数全局样式)
  • 确认 Tailwind 的 purge 配置包含了所有模板文件
  • 把全局样式(背景色、字体、间距)和组件样式分开

结果:CSS 文件 12 KB,一次加载后缓存,后续页面不重复下载。


6. 预加载关键资源

首屏需要的关键资源(Logo、背景图)用 <link rel="preload"> 提前加载:

<link rel="preload" href="/logo-512.webp" as="image" />
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin />

非关键资源(文章配图、非首屏图片)用 loading="lazy" 延迟加载,等用户滚动到附近时才加载。


7. 减少外部依赖

本站的依赖清单很短:

astro, @astrojs/sitemap, tailwindcss

三个包。没有 UI 组件库,没有图标库,没有动画库。每个外部依赖都会增加构建时间和产物大小,选择依赖之前问自己一句:这个功能我能不能自己写 20 行代码搞定?

图标全部内联 SVG(放在 Astro 组件里),不需要 Font Awesome 或 Heroicons。


8. 安全头 + 缓存策略

服务器配置了合理的缓存头,让浏览器缓存静态资源:

# 字体和图片缓存 30 天
location ~* \.(webp|png|svg|woff2)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
}
# HTML 不缓存(确保内容更新后用户看到最新版本)
location ~* \.html$ {
    expires -1;
}

9. 持续监控

性能优化不是一劳永逸的。每次新增功能、升级依赖后,Lighthouse 都有可能降分。我保持的做法:

  • 每次构建后跑一次 Lighthouse(用 lighthouse-ci 在 CI 里自动跑)
  • 设置阈值告警:Performance 低于 95 就报错
  • 每月检查一次 Core Web Vitals 数据(Google Search Console 里看)

总结:九项优化效果

优化项效果工作量
图片 WebP 化图片体积减少 89%1 小时
构建产物分析JS 从 87KB 降到 0KB2 小时
零 JS 框架选型LCP 1.7s, TBT 0ms选型阶段
字体加载优化消除 FOIT(白屏)10 分钟
CSS 分层CSS 23KB → 12KB30 分钟
预加载LCP 降低 200-300ms10 分钟
减少外部依赖构建时间减半持续
缓存策略二次访问加载时间 < 1s30 分钟
持续监控防回退一次性配置

性能优化的核心不是”把所有指标拉到满分”,而是”用最小的投入拿到最大的用户体验改善”。 图片格式升级这一项,投入 1 小时,换来 89% 的体积缩减,性价比远高于花一周时间优化 0.1 秒的 LCP。

需要前端性能优化或官网建设服务?联系我们,说清你的网站技术栈与性能瓶颈,24 小时内回可行性。

相关阅读

常见问题

Lighthouse 分数到底有没有意义?

有参考意义,但不应该成为目标。Lighthouse 衡量的是一组固定的性能指标(LCP、CLS、TBT、SI),这些指标覆盖了大部分用户体验场景。但分数 100 不代表你的网站真的快——它只代表在测试环境下达到了 Google 的基准线。真正的用户体验还要考虑网络条件、设备性能、后端延迟。把 Lighthouse 当作诊断工具,不是 KPI。

图片优化应该做到什么程度?

最低标准:所有图片都转成 WebP 或 AVIF 格式,尺寸不超过实际显示尺寸的 2 倍。如果每张图控制在 30-50KB 以内,就已经比 90% 的网站做得好。更进一步:用 srcset 提供多分辨率版本,让浏览器根据屏幕密度自动选择。再进一步:关键图片(首屏所见)用 <link rel="preload"> 提前加载,非关键图片用 loading="lazy" 延迟加载。

WebFont 对性能影响大吗?

很大。一个未优化的字体文件 100-300KB,如果阻塞渲染,会直接拉长 LCP 几百毫秒。建议:① 用 font-display: swap 避免字体阻塞渲染;② 用 woff2 格式(压缩率最高);③ 只加载你实际用到的字重和字符集(subset);④ 考虑用系统字体栈作为备选——很多用户其实不介意你的设计字体。

框架选型对性能的影响有多大?

框架选型影响的是"性能基线"。Astro 这种零 JS 默认的框架,基线就很高——首页不加载任何 JavaScript,Lighthouse 自然就高。Next.js 的 SSR 在复杂页面下也能达到好的 LCP,但 TBT(总阻塞时间)可能因为 hydration 而偏高。框架选型决定了你"不做什么就能拿到多少分",比优化手段更根本。

本文来自 AI Enable Harness 一线交付实践。需要同类系统或优化服务?

订阅博客更新

新文章发布后第一时间邮件通知。不定期发送,不推销。

订阅 →