Hugo 静态网站图片加速:8.6MB 到 310KB 的实战记录
用 Hugo 内置图片处理管道把 8.6MB 的 PNG 背景图压缩到 310KB WebP,体积缩小 28 倍,弱网下加载从 5-10 秒降到 1 秒内。完整实操记录。
1. 为什么要做图片加速
静态网站加载卡顿,图片往往是最大元凶:
| 原因 | 说明 |
|---|---|
| 图片体积大 | 一张 2560×1440 PNG 可能有 8-10MB |
| 格式低效 | PNG 无损压缩,适合截图但不适合照片 |
| 没有懒加载 | 页面一次性加载所有图片 |
| 没有缓存 | 每次访问都重新下载 |
核心思路: 让浏览器下载更小的文件。
2. Hugo 图片处理管道原理
Hugo 内置图片处理能力,构建时自动完成:
$$原始图片 (assets/img/wall4.png)
↓ Hugo 构建时处理
Resize "1920x webp q75"
↓
优化后图片 (public/img/wall4_hu_xxx.webp)$$
| 操作 | 语法 | 说明 |
|---|---|---|
| 缩放 | Resize "800x" | 限制宽度 800px |
| 裁剪 | Crop "800x600" | 裁成指定尺寸 |
| 填充 | Fill "800x600" | 填充并居中裁剪 |
| 转格式 | webp / jpg / png | WebP 体积最小 |
| 质量 | q75 | 75% 质量(默认 75) |
3. 方案一:CSS 背景图优化(实测)
步骤 1:图片放到 Hugo 资源目录
mkdir -p web-site/assets/img
cp 你的图片.png web-site/assets/img/wall4.png
步骤 2:创建处理 partial
新建 layouts/partials/hero-bg.html:
{{/* Hero 背景图 — 用 Hugo 图片管道优化:转 WebP + 缩放到 1920px */}}
{{ $img := resources.Get "img/wall4.png" }}
{{ $webp := "" }}
{{ if $img }}
{{ $webp = $img.Resize "1920x webp q75" }}
{{ end }}
{{ if $webp }}
<style>
:root {
--tn-hero-bg: url('{{ $webp.RelPermalink }}');
}
</style>
{{ end }}
步骤 3:在页面模板中注入
在所有 baseof 模板的 <head> 里加一行:
<head>
{{ partial "head.html" . }}
{{ partial "hero-bg.html" . }} <!-- ← 加这行 -->
</head>
步骤 4:CSS 里引用变量
.tn-hero {
background:
linear-gradient(rgba(18, 32, 88, 0.75), rgba(18, 32, 88, 0.85)), // 遮罩
var(--tn-hero-bg, url('/wall4.png')) center center / cover no-repeat; // 背景图
}
步骤 5:重新构建
hugo
find public -name "*.webp"
# 输出类似:public/img/wall4_hu_8de1eac147519903.webp
4. 方案二:正文图片优化(shortcode)
markdown 里直接  不会走 Hugo 管道。写个 shortcode:
新建 layouts/shortcodes/img.html:
{{ $img := .Page.Resources.GetMatch (.Get "src") }}
{{ $alt := .Get "alt" | default "" }}
{{ $width := .Get "width" | default "800x" }}
{{ if $img }}
{{ $webp := $img.Resize (printf "%s webp q75" $width) }}
<figure>
<img src="{{ $webp.RelPermalink }}"
alt="{{ $alt }}"
loading="lazy"
width="{{ $webp.Width }}" height="{{ $webp.Height }}" />
{{ with .Get "caption" }}<figcaption>{{ . }}</figcaption>{{ end }}
</figure>
{{ end }}
文章里使用:
{{< img src="photo.jpg" alt="产品图" caption="图1: 产品外观" >}}
注意: 图片必须放在文章同级目录(Page Bundle):
$$content/blog/我的文章/
├── index.md ← 文章(注意是 index.md 不是 xxx.md)
└── photo.jpg ← 图片和文章放一起$$
5. 方案三:懒加载
所有 <img> 加一个属性,浏览器滚动到才加载:
<img src="photo.webp" loading="lazy" />
正文图片用这个就够了,CSS 背景图懒加载需要 JS(IntersectionObserver)。
6. 效果验证方法
浏览器 Network 面板(推荐)
- 打开页面按 F12
- 切到 Network 标签
- 网络下拉选 Regular 3G 或 Slow 3G
- 勾选 Disable cache
- Ctrl+Shift+R 强制刷新
- 看图片那行的 Time 列
curl 测速
curl -o /dev/null -w "耗时: %{time_total}s 大小: %{size_download} bytes\n" \
http://localhost:1313/img/wall4_hu_8de1eac147519903.webp
实测对比
| 版本 | 原始大小 | 优化后 | Regular 3G 耗时 |
|---|---|---|---|
| PNG 2560×1440 | 8.6 MB | — | 5-10 秒 |
| WebP 1920px q75 | — | 310 KB | <1 秒 |
体积缩小 28 倍,弱网下加载从 5-10 秒降到 1 秒内。
7. 进阶技巧
7.1 多尺寸响应式(srcset)
根据屏幕宽度加载不同尺寸:
{{ $img := resources.Get "img/hero.png" }}
{{ $sm := $img.Resize "640x webp q75" }}
{{ $md := $img.Resize "1280x webp q75" }}
{{ $lg := $img.Resize "1920x webp q75" }}
<img src="{{ $lg.RelPermalink }}"
srcset="{{ $sm.RelPermalink }} 640w, {{ $md.RelPermalink }} 1280w, {{ $lg.RelPermalink }} 1920w"
sizes="100vw"
loading="lazy" />
7.2 更激进压缩
$img.Resize "1920x webp q50" // 50% 质量,体积更小
$img.Resize "1920x webp q30" // 30% 质量,适合纯色背景图
7.3 Nginx 缓存
location ~* \.(jpg|jpeg|png|webp|gif|svg)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
7.4 CDN
- Cloudflare:免费套在网站前,自动缓存 + 压缩
- jsDelivr:GitHub/Gitee 仓库静态资源免费 CDN
总结
$$1. 图片放 assets/ 目录
2. 用 resources.Get + Resize "xxx webp q75" 处理
3. CSS 背景图 → 注入 CSS 变量
4. 正文图片 → 自定义 shortcode
5. 加 loading="lazy"
6. 浏览器 DevTools 验证速度$$