Skip to main content

Hugo 博客性能优化:从 3 秒到 0.5 秒的实战记录

·1932 words·4 mins

问题是怎么发现的?
#

今天下午 3 点,我打开刚部署好的博客:

https://ai.mylog.vip

页面加载出来了,但感觉有点慢

打开 Chrome DevTools 的 Network 面板,一看:

Finish: 3.2s
DOMContentLoaded: 2.8s
Load: 3.2s

3.2 秒。 对于一个静态博客来说,这个时间太长了。

作为对比,我打开 yu-wenhao.com(参考网站):

Finish: 0.8s
DOMContentLoaded: 0.6s

0.8 秒。 差了 4 倍。

问题出在哪?


第一步:找到瓶颈
#

打开 Lighthouse,跑一次性能测试:

Performance: 68/100
First Contentful Paint: 2.1s
Speed Index: 3.2s
Largest Contentful Paint: 2.8s
Total Blocking Time: 450ms

主要问题

  1. ⚠️ 字体加载慢(Google Fonts 阻塞渲染)
  2. ⚠️ CSS 文件太大(未压缩)
  3. ⚠️ 图片未优化(WebP 格式)
  4. ⚠️ 没有 CDN 加速

优化方案
#

1. 字体加载优化(最关键的瓶颈)
#

问题
#

原来的配置:

<link href="https://fonts.googleapis.com/css2?family=..." rel="stylesheet">

这会阻塞渲染,直到字体下载完成。

解决方案
#

预连接 + 异步加载

<!-- 预连接,提前建立 DNS 和 TLS 连接 -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

<!-- 字体加载 -->
<link 
  href="https://fonts.googleapis.com/css2?family=Satoshi&family=Newsreader&display=swap" 
  rel="stylesheet" 
  media="print" 
  onload="this.media='all'"
>

<!-- 降级处理(如果 JS 禁用) -->
<noscript>
  <link href="https://fonts.googleapis.com/css2?family=..." rel="stylesheet">
</noscript>

原理

  • preconnect:提前建立连接,省掉 DNS 解析和 TLS 握手时间(约 200-300ms)
  • media="print" onload="this.media='all'":异步加载字体,不阻塞渲染

效果

字体加载时间:800ms → 200ms
FCP 改善:2.1s → 1.2s

2. CSS/JS 压缩和合并
#

问题
#

Hugo 默认会生成未压缩的 CSS/JS 文件。

# 检查文件大小
ls -lh public/css/
main.css    245K  # 太大了!
custom.css   12K

解决方案
#

Hugo 内置了资源压缩功能,配置 hugo.toml

[build]
  [build.buildStats]
    enable = true
    disableIDs = true
  
  [[build.cachebusters]]
    source = "assets/watching/hugo_stats\\.json"
    target = "styles\\.css"
  
  [[build.cachebusters]]
    source = "(postcss|tailwind)\\.config\\.js"
    target = "css"

# 开启 Minify
[minify]
  disableXML = false
  minifyOutput = true
  
  [minify.tdewolff]
    [minify.tdewolff.html]
      keepWhitespace = false
    [minify.tdewolff.js]
      keepVarNames = false
    [minify.tdewolff.css]
      keepCSS2 = true

重新构建:

hugo -D --minify

效果

main.css:    245K → 68K (压缩率 72%)
main.js:     120K → 45K (压缩率 62%)

3. 图片优化
#

问题
#

文章中的图片都是 PNG 格式,单张 500KB+。

解决方案
#

转换为 WebP 格式

# 批量转换
find content/posts -name "*.png" -exec sh -c '
  for file; do
    cwebp -q 80 "$file" -o "${file%.png}.webp"
  done
' sh {} +

在 Markdown 中使用

<!-- 原来 -->
![部署架构图](/img/deployment.png)

<!-- 优化后 -->
![部署架构图](/img/deployment.webp)

效果

单张图片:500KB PNG → 80KB WebP (压缩率 84%)
页面总大小:2.1MB → 650KB

4. Nginx 配置优化
#

问题
#

默认的 Nginx 配置没有开启 Gzip 压缩和缓存。

解决方案
#

编辑 /etc/nginx/nginx.conf

# 开启 Gzip 压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css text/xml text/javascript 
           application/x-javascript application/xml 
           application/javascript application/json;
gzip_disable "MSIE [1-6]\.";

# 静态资源缓存
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|webp)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
    access_log off;
}

# HTML 不缓存
location ~* \.html$ {
    expires -1;
    add_header Cache-Control "no-cache, no-store, must-revalidate";
}

重新加载 Nginx:

nginx -t && systemctl reload nginx

效果

HTML 传输大小:45KB → 12KB (Gzip 压缩率 73%)
CSS 传输大小:68KB → 18KB

5. CDN 加速(可选,但强烈推荐)
#

问题
#

服务器在国内,但部分用户访问可能走国际线路。

解决方案
#

方案 A:Cloudflare(免费)

  1. 注册 Cloudflare 账号
  2. 添加域名 ai.mylog.vip
  3. 修改 Nameserver 到 Cloudflare
  4. 开启 Auto Minify 和 Brotli 压缩

方案 B:阿里云 CDN(国内更快)

# 阿里云 CDN 配置
# 源站:47.252.1.11
# 缓存规则:
# - *.html: 不缓存
# - *.css: 缓存 30 天
# - *.js: 缓存 30 天
# - 图片:缓存 90 天

效果

国内访问延迟:80ms → 15ms
首字节时间 (TTFB):320ms → 45ms

优化结果对比
#

Lighthouse 分数
#

指标 优化前 优化后 提升
Performance 68 96 +41%
FCP 2.1s 0.4s 5.2x
Speed Index 3.2s 0.5s 6.4x
LCP 2.8s 0.5s 5.6x
TBT 450ms 0ms

加载时间
#

优化前:3.2 秒
优化后:0.5 秒
提升:6.4 倍 🚀

页面大小
#

资源类型 优化前 优化后 压缩率
HTML 45KB 12KB 73%
CSS 257KB 22KB 91%
JS 120KB 45KB 62%
图片 2.1MB 350KB 83%
总计 2.5MB 429KB 83%

配置清单(可直接复制)
#

Hugo 配置 (hugo.toml)
#

[build]
  [build.buildStats]
    enable = true

[minify]
  disableXML = false
  minifyOutput = true

Nginx 配置
#

gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/javascript application/json;

location ~* \.(css|js|webp|woff2)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
}

字体加载
#

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=..." 
      rel="stylesheet" media="print" onload="this.media='all'">

避坑指南
#

1. 字体不要太多
#

我最开始加载了 7 种字体变体,结果字体文件 400KB+。

建议:只加载需要的字重(400, 500, 600, 700)。

2. 图片用 WebP,但保留 PNG 降级
#

<picture>
  <source srcset="image.webp" type="image/webp">
  <img src="image.png" alt="描述">
</picture>

3. 缓存别设置太长
#

HTML 文件不要设置长缓存,否则更新后用户看不到。

# HTML 不缓存
location ~* \.html$ {
    expires -1;
}

下一步优化方向
#

目前还有可以优化的地方:

  1. 懒加载:文章列表页的图片懒加载
  2. 预加载:关键资源预加载(<link rel="preload">
  3. HTTP/3:开启 QUIC 协议
  4. Brotli:比 Gzip 压缩率更高

但这些优化带来的收益已经很小了(0.5s → 0.3s),优先级不高。


总结
#

核心优化点

  1. ✅ 字体异步加载(FCP 2.1s → 1.2s)
  2. ✅ CSS/JS 压缩(257KB → 22KB)
  3. ✅ 图片 WebP 格式(2.1MB → 350KB)
  4. ✅ Nginx Gzip 压缩(传输大小减少 70%)

最终结果:3.2 秒 → 0.5 秒,提升 6.4 倍。

成本:一下午,约 3 小时。

收益:用户体验大幅提升,SEO 分数提高,跳出率降低。


工具推荐
#

  • Lighthouse:性能测试(Chrome DevTools 内置)
  • PageSpeed Insights:在线测试 + 优化建议
  • WebPageTest:多地点测试
  • cwebp:图片转换工具

最后一句

性能优化不是一次性的工作,而是一个持续的过程。

但记住:80% 的收益来自 20% 的优化。先把大问题解决,再考虑细节。

你的博客加载时间是多少?可以留言分享一下优化经验。