我们的静态博客虽然已经部署在了极其强大的 Cloudflare CDN 上,并且开启了 Brotli 压缩,但在实际的 Lighthouse 测速中,依然可能会因为一项极其耗费带宽的资源而丢分——高清图片

尤其是当你写了一篇长文,里面贴满了服务器终端报错截图或者 4K 级别的视频封面时,页面的首屏加载时间(LCP)就会被严重拖垮。今天,我们对 Hexo 博客进行前端性能的最后一次手术:引入 WebP 格式与图片懒加载。

为什么是 WebP?

WebP 是 Google 开发的现代图像格式,相比传统的 PNG/JPEG:

格式 压缩率 透明度支持 动画支持
JPEG 基准
PNG 中等
WebP 高 25-35%
AVIF 高 50%

WebP 的浏览器支持率已超过 97%,在 2024 年几乎可以放心使用。AVIF 压缩率更高但编码速度慢,适合离线构建场景。

方案一:构建时批量转换

最彻底的方案——在 Hexo 生成静态文件前,自动将所有图片转换为 WebP:

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
# convert-to-webp.sh — 放在项目根目录

find source/ -type f \( -name "*.jpg" -o -name "*.jpeg" -o -name "*.png" \) | while read img; do
webp="${img%.*}.webp"
if [ ! -f "$webp" ] || [ "$img" -nt "$webp" ]; then
cwebp -q 80 "$img" -o "$webp"
echo "Converted: $img$webp"
fi
done

将这个脚本集成到构建流程的前置步骤中。在 Cloudflare Pages 的构建命令中:

1
bash convert-to-webp.sh && hexo generate

方案二:在 Markdown 中统一处理

如果不想修改构建流程,可以在 Markdown 中嵌入 HTML 来实现:

1
2
3
4
<picture>
<source srcset="/images/screenshot.webp" type="image/webp">
<img src="/images/screenshot.png" alt="服务器监控大盘" loading="lazy">
</picture>

浏览器会优先加载 WebP,不支持时降级到 PNG。

图片懒加载完整实现

原生 HTML 的 loading="lazy" 属性已经得到主流浏览器支持,但这只是基础。配合 JavaScript 可以实现更精细的控制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 使用 Intersection Observer API 实现懒加载
document.addEventListener('DOMContentLoaded', () => {
const images = document.querySelectorAll('img[data-src]');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.removeAttribute('data-src');
observer.unobserve(img);
}
});
}, {
rootMargin: '200px 0px', // 提前 200px 加载
threshold: 0.01
});

images.forEach(img => observer.observe(img));
});

rootMargin: '200px 0px' 是关键——它让图片在即将进入视口 200px 之前就开始加载,用户滚动到图片位置时已经下载完成,体验几乎无感。

响应式图片与 srcset

不同设备屏幕宽度不同,应该加载不同尺寸的图片。srcset 属性让浏览器自动选择最合适的版本:

1
2
3
4
5
6
7
8
9
10
11
<img
src="/images/screenshot-800w.webp"
srcset="/images/screenshot-400w.webp 400w,
/images/screenshot-800w.webp 800w,
/images/screenshot-1200w.webp 1200w"
sizes="(max-width: 600px) 400px,
(max-width: 900px) 800px,
1200px"
loading="lazy"
alt="服务器监控大盘截图"
>

Lighthouse 实战验证

配置完成后,在 Chrome DevTools 中运行 Lighthouse 审计。重点关注以下指标:

指标 含义 目标
LCP 最大内容渲染时间 < 2.5s
FID 首次输入延迟 < 100ms
CLS 累积布局偏移 < 0.1
TBT 总阻塞时间 < 300ms

关键技巧:一定要给所有图片设置明确的 widthheight 属性,否则浏览器无法预留空间,图片加载完成后会引发布局跳动(CLS 扣分)。

总结

WebP + 懒加载 + 响应式图片,这三板斧组合下来,一个原本因为图片而拖累性能的博客页面,Lighthouse 评分可以从 60 分提升到 95 分以上。更重要的是,这些优化完全免费、零服务器负担,纯粹是前端构建层面的升级。