一、前言
本文旨在介绍如何通过 WebP图片格式 提高 Halo博客 的网页加载速度,以提高访客浏览页面的体验。
二、WebP是什么
WebP 是一种现代图片格式,可为网络上的图片提供出色的无损和有损压缩。使用 WebP,网站站长和 Web 开发者可以创建更小、更丰富的图片,从而提高网页加载速度。
——谷歌开发者文档
关于浏览器的支持情况,可参阅官网文档:哪些网络浏览器本身支持 WebP?
注:WebP 是开源的,最新源码(需要科学上网)
注:WebP 与 VP8 的比特流兼容,宽度和高度均为 14 位。 WebP 图片的最大像素尺寸为 16383 x 16383。
三、为什么要使用 WebP
云服务器的带宽价格实在是太贵了,个人建站购买云服务器通常只有3M、4M之类的带宽。
按照本站的实际体验来看,3M的带宽,遇到多图页面(甚至有时仅仅是六篇文章的列表页头图)加载起图片就明显吃力,往往需要好一会儿才能加载完毕,对于访客而言体验真的很差。(更别说那种几十张大体积PNG图的页面)
(如果你的带宽够大,那么考虑过并发场景呢?)
所以,急需一种能够提高图片加载速度的方式。
在 花钱提升带宽、进行CDN加速 和 在不影响图片观感效果情况下降低图片体积 的选项中,我们自然是倾向于后者。
于是,本文选用 WebP 图片格式,使得博客页面上展示的图片体积可以有较大幅度的缩小,从而带来了加载性能的提升。(毕竟需要加载的数据量小了,加载速度自然就快了)
Halo官网本身其实也应用了WebP来输出图片(不信你可以去研究看看),Halo官网也有相关的优化指引文章:优雅的让 Halo 支持 webp 图片输出
另外,还有一点操作起来有些麻烦的建议(当然,你可以选择不做):上传图片前,先无损压缩一下。(即,从源头降低图片体积)
注:其实降低图片体积,还有一个好处就是降低服务器流量消耗(特别是那些每月有免费流量上限的云服务器)
四、如何使用 WebP(方式一)
将网站上的图片全部变成 WebP 图片格式,每次上传图片前都先去将图片转换为 WebP格式。
注:使用这种方式的话,很难处理存量图片的引用。因为如果你把图片变成WebP了,博文里的引用链接也要跟着改。
评价:不太现实,也麻烦,所以建议使用 五、如何使用 WebP (方式二)
4.1 转成 WebP 途径一:在线网站
网上有一些网站支持在线转换,可以直接使用,请自行去找。
4.2 转成 WebP 途径二:官方工具
首先,依据平台,下载 WebP 软件包:下载并安装 WebP
将预编译好的程序包解压到某个文件夹内。
参考谷歌提供的操作指南进行操作。
以下为有损压缩的简单示例:
前置准备:
Windows11环境下已下载并解压 WebP 软件包。
已准备了一个等待被转换的图片,这里为 Test.jpg 图片。
执行命令:cwebp.exe -q 80 Test.jpg -o Test.webp
其中:
cwebp.exe:为 WebP 解压文件夹内bin目录下的对应文件,执行命令时需要指向这个文件。
-q:指定 0 和 100 之间的 RGB 通道压缩因数。默认值为 75。如果是有损压缩(默认),微小系数生成的文件体积较小,质量较低。使用 100 值可以实现最佳质量。对于无损压缩(由
-lossless
选项指定),较小的系数可以加快压缩速度,但生成的文件会更大。使用 100 值可以实现最大压缩。Test.jpg:等待被转换的图片。
Test.webp:转换后的 WebP图片文件路径(文件名)。
结果展示(图片大小明显下降):
结果展示(图片显示效果差距不明显):
五、如何使用 WebP (方式二)
此方式不需要改变原有的上传图片、引用图片逻辑,存量图片数据无需变更,未来的图片操作上也不需要变化,相当于是隐性地做了优化。另外,这种方式相对独立,可插拔。
本文基于的是 webp-sh 组织开源的 webp_server_go 。
注:这里是在 部署halo的服务器 上操作。
注:webp_server_go 实测用一段时间后,大概会占用四五百兆的内存,所以需要服务器内存有足够的空间。
注:Halo V2.19.0 版本开始,因为 halo 会自行生成缩略图,所以大大降低了图片资源的加载速度。如果实测下来体验不是很糟糕的话,建议不必额外使用webp_server_go。
5.1 WebP Server Go
介绍(内容源自:0.11.0发布文档 + 简介页):
大概原理:当我们请求一张图片时,使用 Web 代理工具转发到 webp_server_go 服务上进行处理,处理完成之后返回 WebP 格式的图片,并且会缓存处理后的图片以供后面的访问。
开源源码(开源协议:GPLv3 许可):GitHub上
目标:旨在不改变原始 URL 的情况下通过通过动态(On the fly)优化/压缩原始图片到更加现代的格式,解决网站输出较大体积的老格式图片(如
JPG
、PNG
)导致服务器额外带宽开销和加载速度缓慢的问题,从而提高网页响应速度并提升页面的 Pagespeed 评分。使用 WebP Server Go 可以:保持原始图片地址不变,将图片体积缩小并以更现代的图片格式(例如
webp
,avif
)输出。无需更改图片地址,URL 中的图像地址仍可以
jpg
、png
等结尾,但输出为webp
或avif
格式。由于
webp
和avif
等格式有浏览器限制(例如 Firefox 77~92 版本不支持avif
格式),所以 WebP Server Go 会根据浏览器信息自动输出一个浏览器能接受的且体积最小的图片。
5.2 Linux + Nginx 实操
本文基于:
Ubuntu 22.04
WebP Server Go V0.11.0
Halo V2.13
参考:
注:写这篇文章时,官网上还挂有“服务存在内存泄漏的问题”的提示,我去看了相关的 issue,似乎在 0.6.0 和 0.9.? 做了相关的优化,不确定是否已经完全解决。(所以,建议使用新版本,不要使用旧版本的 WebP Server Go )
注:官方目前推荐是用 docker 来使用 WebP Server Go,但是我这里没有使用 docker。如果你准备基于 docker 来使用WebP Server Go,则可以参考官方文档:Usage with Docker(Recommended)。
注:目前 WebP Server Go 的更新还蛮频繁的,不确定等你看到这篇文章时,已经变化到何等程度,还是得多看官网文档啊!
5.2.0 确定用户
为避免权限问题,下文简单起见使用 执行halo服务的同一个用户 来执行以下操作(否则你需要给执行 WebP Server Go 的用户赋予读取 halo 图片附件目录的权限)。
5.2.1 新建文件夹
现在,先创建等下要用来放 WebP Server Go 一系列文件的目录。(具体这个文件夹放哪里,取决于你)
例如创建 webp 文件夹,执行命令:mkdir webp
进入新建的目录,执行命令:cd webp
5.2.2 下载相关依赖
详情参考: Usage with Binary(Advanced)
执行命令(需要用Root用户):apt install libvips-dev
5.2.3 下载编译好的服务文件
(如果有能力,也可以选择自己编译)
先去看一下 WebP Server Go 的发行版本:Releases
选择你想要使用的版本,复制下载链接。
在刚刚创建的新文件夹内,利用下载链接下载编译好的文件:
执行命令: wget https://github.com/webp-sh/webp_server_go/releases/download/0.11.0/webp-server-linux-amd64 -O webp-server
其中:
-O webp-server:(注意,是大写的 O )表示将下载下来的数据,存储到指定名字的文件中(本例中文件名为 web-server)。
现在下载下来的这个 webp-server,还不能执行,需要先配置执行权限。
给拥有者配置文件执行权限,执行命令:chmod u+x webp-server
5.2.4 配置文件
现在,开始编写 webp-server 执行需要的配置文件。
执行命令:vi config.json
{
"HOST": "127.0.0.1",
"PORT": "3333",
"QUALITY": "80",
"IMG_PATH": "/path/to/attachments",
"EXHAUST_PATH": "./exhaust",
"IMG_MAP": {},
"ALLOWED_TYPES": ["jpg", "png", "jpeg", "bmp", "gif", "svg", "heic", "nef", "webp"],
"CONVERT_TYPES": ["webp"],
"STRIP_METADATA": true,
"ENABLE_EXTRA_PARAMS": false,
"READ_BUFFER_SIZE": 4096,
"CONCURRENCY": 512,
"DISABLE_KEEPALIVE": false,
"CACHE_TTL": 259200
}
各个参数可参考官方文档:完整配置
其中重点:
QUALITY:图片质量,值范围为 0-100,100表示无损压缩。默认值:80。
IMG_PATH:原始图片目录。如果你使用的是 Nginx代理,则这里应该是 location 匹配路径前的那一部分路径。例如你是按照本文配置流程,则应该是到attachement 这个目录的路径。
EXHAUST_PATH:WebP Server Go 缓存处理过的 WebP 图片存放目录。可自定义一个位置,不需要提前创建文件夹。
IMG_MAP:如果你的原始图片目录不止一个,则可以参考官网文档配置这个配置项。
CONCURRENCY:最大并发连接数,需要依据你的实际情况来。默认值:262144,我这里是降低到512。
5.2.5 启动服务
可以参考Halo的官方文章:优雅的让 Halo 支持 webp 图片输出 用 systemd 管理服务。
WebP Server Go 支持一些命令(包括生成 systemd 的 service 文件、预处理转换原图片目录文件为 WebP 等),可参考文章:[Go 开源推荐] webp_server_go —— 可自动将 jpg, jpeg, PNG 图片进行压缩的 WebP 服务
我希望是自己手动管理,所以自行写脚本启动,下面是操作步骤。
先新建一个文件夹,用于存储执行日志。
执行命令:mkdir logs
开写启动脚本。
执行命令:vi webpServerStart.sh
#!/bin/bash
nohup ./webp-server --config=/path/to/webp/config.json >> /path/to/webp/logs/"`date +%Y%m%d`.log" &
设置脚本为可执行。
执行命令:chmod u+x webpServerStart.sh
执行脚本:./webpServerStart.sh
注:自己写脚本启动的话,如果要停止服务运行,就得通过杀进程的方式。
5.2.6 Nginx 配置转发
Nginx的安装和使用说明,可参考:Linux nginx的安装与入门
此时看你之前 Nginx 是用什么用户管理的,就用哪个用户操作。
编辑代理 halo服务的 nginx配置文件。
例如执行命令:vi yokila.conf
在 代理halo服务的server 中添加以下内容:
location ^~ /upload/ {
proxy_pass http://127.0.0.1:3333;
proxy_set_header X-Real-IP $remote_addr;
proxy_hide_header X-Powered-By;
proxy_set_header HOST $http_host;
add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
}
注意修改内容保存。
然后就可以重新加载Nginx配置了。
执行命令:nginx -t
执行命令:nginx -s reload
六、实际体验
在浏览器里,摁 F12
开启开发者模式,刷新你的博客页面。
注:如果出错的话,WebP Server Go 会自动输出原图片,相当于没做优化,仅看页面上看不出来是是否正常进行了压缩。
查看网络请求的信息,看到图片是 WebP 类型,说明很成功!
另外,可以观测一下 配置里的这个 EXHAUST_PATH 文件夹,看看有无正常生成 webp 文件缓存。
还有观测一下 日志文件,看看是否有报错。
注:如果发现有一些图没压缩,则可以依据日志进行问题排查。