网站性能优化实战:从 8.88s 到 2s
性能优化webfontnginxgzipCDN
问题
一个 Vue3 + Vuetify + Vite 的个人站点,首次加载 8.88 秒,有时超过 11 秒。Chrome DevTools Performance 面板分析发现,耗时主要卡在 webfont 加载上——阻塞了 JS 执行长达 6 秒以上。
诊断
Vuetify 默认使用 Material Design Icons(@mdi/font),字体文件通过 CSS @font-face 声明加载。浏览器遇到外部字体资源时,默认行为是阻塞渲染直到字体下载完成。这不是 bug,是规范——但对于首屏体验来说,这个代价不可接受。
第一步:CDN 异步加载 webfont
将字体 CSS 从打包产物中剥离,改用 jsDelivr CDN 加载,并通过 rel="preload" + onload 切换的方式避免阻塞:
<link
rel="preload"
as="style"
onload="this.rel='stylesheet'"
href="https://cdn.jsdelivr.net/npm/@mdi/font@5.x/css/materialdesignicons.min.css"
/>
rel="preload" 让浏览器以高优先级下载资源但不阻塞渲染,下载完成后通过 onload 将 rel 切换为 stylesheet 应用样式。
首屏时间从 8.88s 降到 2s 以内。
第二步:nginx gzip 压缩
对文本类资源开启 gzip,减少传输体积:
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 4;
gzip_types text/plain text/css application/json application/javascript
text/xml application/xml application/xml+rss text/javascript;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_disable "MSIE [1-6]\.";
几个要点:
gzip_comp_level 4:压缩级别取中间值,平衡 CPU 开销和压缩率gzip_types:显式指定需要压缩的 MIME 类型,避免漏压或误压gzip_vary on:让代理服务器根据Accept-Encoding头正确缓存
第三步:静态资源缓存
对不常变的资源设置远未来过期时间,配合文件名哈希实现缓存更新:
# 图片、CSS、JS
location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|webp|svgz?)$ {
expires 7d;
}
# 字体
location ~* \.(?:ttf|ttc|otf|eot|woff2?)$ {
add_header Access-Control-Allow-Origin "*";
expires 7d;
}
字体文件需要 CORS 头,否则跨域 CDN 场景下会加载失败。
结果
优化后首屏加载稳定在 2s 内,资源体积经 gzip 压缩后平均减少 60%+。核心结论:性能问题的根因很少在表面——先定位瓶颈,再选工具,顺序不能反。