发布于

网站性能优化清单:从 69KB 的首页说起

作者
  • avatar
    姓名
    小欧

先量化,再优化

性能优化最忌讳「凭感觉改」。我的第一步是把现状量化:

# 首页 HTML 体积(未压缩)
curl -s -o /dev/null -w 'size=%{size_download}\n' https://example.com/

# 首屏资源清单
curl -s https://example.com/ | grep -oE '/_next/static/[^"]+\.(js|css)' | sort -u

# 构建产物体积
du -sh .next .next/static

我拿到的基线是:首页 HTML 69.5 KB,且响应头里没有 Content-Encoding——意味着传输时完全没有压缩。

一、传输层:先解决最粗的问题

开启压缩

Next.js 自带压缩开关,反代层也应该兜底:

// next.config.js
module.exports = {
  compress: true,
}
# Nginx 兜底(Brotli 优先级高于 gzip)
brotli on;
gzip on;
gzip_types text/html text/css application/javascript application/json image/svg+xml;

静态资源长缓存

Next.js 的 /_next/static/* 文件名带内容哈希,可以放心用永久缓存:

location /_next/static/ {
    expires 1y;
    add_header Cache-Control "public, max-age=31536000, immutable";
}

而 HTML 不能永久缓存,用 stale-while-revalidate 兼顾速度和新鲜度:

Cache-Control: public, max-age=0, s-maxage=3600, stale-while-revalidate=86400

二、资源体积

找出真正的大头

不要猜,用分析器:

ANALYZE=true npm run build   # @next/bundle-analyzer

按需加载非首屏内容

音乐播放器、评论区、图表这类东西用户首屏根本看不到,用动态导入:

const MusicPlayer = dynamic(() => import('@/components/MusicPlayer'), {
  ssr: false,
  loading: () => <PlayerSkeleton />,
})

图片

  • 一律走 next/image,自动转 WebP/AVIF 并生成多尺寸
  • 必须写 width / height,否则会造成 CLS
  • 首屏大图加 priority,其余全部懒加载

大文件不要进仓库

音频、视频、大图放在 public/ 会带来三个问题:仓库膨胀、部署变慢、源站带宽被吃满。

正确做法是放对象存储 + CDN:

<audio src="https://cdn.example.com/music/song.mp3" controls />

三、渲染层

手段效果
RSC / 静态生成内容页几乎零 JS
next/font 自托管字体消除第三方字体请求,避免 FOIT
字体子集化中文字体动辄几 MB,必须裁剪常用字
图片 priority提升 LCP
骨架屏改善 CLS 与感知性能

四、验证

优化完必须用数据说话,推荐三个工具:

  1. Lighthouse(Chrome DevTools)—— 综合分与诊断建议
  2. PageSpeed Insights —— 真实用户数据(CrUX)
  3. Web Vitals 上报 —— 把 useReportWebVitals 的结果落库,观察趋势
import { useReportWebVitals } from 'next/web-vitals'

useReportWebVitals((metric) => {
  navigator.sendBeacon('/api/vitals', JSON.stringify(metric))
})

五、可直接复用的清单

传输

  • 全站开启 Brotli / gzip
  • 静态资源 immutable 长缓存
  • HTML 使用 stale-while-revalidate

体积

  • 用 bundle analyzer 定位 Top 3 大包并拆分
  • 非首屏组件动态导入
  • 大文件移出仓库,走 CDN
  • 图片统一 next/image + 显式尺寸

渲染

  • 能用 RSC 的不用客户端组件
  • 字体自托管 + 子集化
  • 首屏图片加 priority

监控

  • 采集 Web Vitals 并看趋势
  • CI 里加性能门禁,防止退化

优化的终点不是「感觉快了」,而是「指标达标且不退化」。