前端性能优化实战:从 Lighthouse 50 到 100 的工程方法
性能优化不是"压到多少分就交差",而是理解每一分从哪来、代价多大。本文从本站的优化过程出发,拆解九项优化手段:图片格式、构建产物分析、字体加载、CSS/JS 分层策略。附优化前后的 Lighthouse 对比数据。【点击查看九项优化手段】
先说结论:性能优化是投资,不是成本
本站从最初版本到现在的 Lighthouse 100/100/100,不是靠某一次”优化大招”达成的,而是一步步加出来的。每次加的代价都很小,但积累起来效果明显。
本文不讲理论,只说我在本站实际做的九件事,每件都附带优化前后的数据。
1. 图片格式升级:PNG → WebP
这是性价比最高的优化。本站所有图片从 PNG 转为 WebP:
| 图片 | 原 PNG | WebP | 缩减 |
|---|---|---|---|
| OG 默认图 | 154 KB | 10 KB | 93% |
| Logo | 172 KB | 14 KB | 92% |
| 微信二维码 | 156 KB | 30 KB | 81% |
| 苹果图标 | 32 KB | 4.5 KB | 86% |
四张图从 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 降到 0KB | 2 小时 |
| 零 JS 框架选型 | LCP 1.7s, TBT 0ms | 选型阶段 |
| 字体加载优化 | 消除 FOIT(白屏) | 10 分钟 |
| CSS 分层 | CSS 23KB → 12KB | 30 分钟 |
| 预加载 | LCP 降低 200-300ms | 10 分钟 |
| 减少外部依赖 | 构建时间减半 | 持续 |
| 缓存策略 | 二次访问加载时间 < 1s | 30 分钟 |
| 持续监控 | 防回退 | 一次性配置 |
性能优化的核心不是”把所有指标拉到满分”,而是”用最小的投入拿到最大的用户体验改善”。 图片格式升级这一项,投入 1 小时,换来 89% 的体积缩减,性价比远高于花一周时间优化 0.1 秒的 LCP。
需要前端性能优化或官网建设服务?联系我们,说清你的网站技术栈与性能瓶颈,24 小时内回可行性。
相关阅读
- Astro vs Next.js 静态站选型实践 —— 框架选型对性能基线的影响
- GEO 优化实战:让 AI 助手能搜索到你的网站 —— 性能优化是 GEO 基建的一部分
常见问题
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 而偏高。框架选型决定了你"不做什么就能拿到多少分",比优化手段更根本。