使用WebP Server Go来加速站点本地图片访问速度
临近毕业,要到自己为站点续命的时候了。想减少开销,减少一些潜在的意外,故挪掉了一直在用的云存储(大部分文件是反代uploads
目录并静态内容迁移以使用 CDN 节点进行加速,小部分文件为自上传的云存储)。这样一来,之前那些随手传上去的图片不是那么小,没有了 CDN 端上的 WebP 自动转换,图片加载速度的确是慢了不少。
然后经过搜索,找到了这么个基于 Go 语言写的这么一个服务端程序,可以自动把普通格式的图片转为 WebP 或者是 AVIF 格式的图片(但 AVIF 的转换对服务器的性能要求极高,详见后文)
安装步骤
- 安装用于转换 AVIF 的依赖(建议别装,性能要求高,虽说就几行终端指令的事,但事后感觉还是白弄,具体命令见 Github)
- 在版本发布页下载最新的构建
- 按照下面的方法生成配置文件(Linux 终端)
./webp-server -dump-config > config.json
config.json
内的文件默认如下:
{
"HOST": "127.0.0.1",
"PORT": "3333",
"QUALITY": "80",
"IMG_PATH": "/path/to/pics",
"EXHAUST_PATH": "/path/to/exhaust",
"ALLOWED_TYPES": ["jpg","png","jpeg","bmp"],
"ENABLE_AVIF": false
}
其中,HOST
地址建议保持这个本地回环地址,只让Nginx
本地反代这个服务端就行,比较优雅。端口可以自定,但其实禁了公网访问保持默认也行。关于两个路径,感觉官方文档写的挺明白的,下面简单翻译一下。
Config 文件示例
下面的示例,分别是图片的存储路径与网站 URL 的路径的示例
In the following example, the image path and website URL.
Image Path(图片的存储路径) | Website Path(网站 URL 路径) |
---|---|
/var/www/img.webp.sh/path/tsuki.jpg | https://img.webp.sh/path/tsuki.jpg |
config.json
配置文件里的IMG_PATH
项应该这样像下面这种填法
TheIMG_PATH
insideconfig.json
should be like:
IMG_PATH |
---|
/var/www/img.webp.sh |
EXHAUST_PATH
是程序用于生成webp
文件的缓存文件夹。如果将缓存文件夹的路径EXHAUST_PATH
设置为/var/cache/webp
,那么示例中的这张图片的缓存文件就会被存到/var/cache/webp/pics/tsuki.jpg.1582558990.webp
EXHAUST_PATH
is cache folder for outputwebp
images, withEXHAUST_PATH
set to/var/cache/webp
in the example above, yourwebp
image will be saved at/var/cache/webp/pics/tsuki.jpg.1582558990.webp
.
AVIF 强烈建议设置为false
- 启动 WebP Server(
/path/to/config.json
替换为真实的路径)
./webp-server --config=/path/to/config.json
- Nginx 反代,直接在你自己的站点配置文件里,追加规则。注:Nginx 的配置文件更改之后,需要重载配置文件或者是重启 Nginx 才会生效(一般只重载配置文件就行)
location ~* \.(?:jpg|jpeg|gif|png)$ {
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';
}
更多内容,详见官方文档:https://docs.webp.sh/usage/basic-usage/
为什么我不推荐开启 AVIF
起初看项目的 README 里,是这样写的:
AVIF support is disabled by default as converting images to AVIF is CPU consuming.
心想,可能只是在高并发的时候对性能有影响吧,于是开启了。因为自己一直用的 Edge 浏览器是不支持 AVIF 的,电脑端的 Chrome 和我手机上的 Safari 是支持 AVIF 的。直到我拿起我的手机,才发现问题所在,然后又下载了 Chrome,也复现了这个问题。进缓存目录一看,生成的 AVIF 文件的大小为 0kb,并且有报错:
time="2022-11-30 12:16:21" level=warning msg="Can't encode source image: encoder error: codec init error to AVIF" func="[120:main.avifEncoder()]"
time="2022-11-30 12:16:21" level=info msg="AVIF@80.00%: /resource/avatar.jpg->/resource/avatar.jpg.1663669630.avif 30850->0 0.00% deflated" func="[153:main.convertLog()]"
找了一圈,不是因为缺少刚才最开始那个依赖而报错,接着搜,搜到了另一个类似项目的 issues 的评论区,结果...
当初是知道性能开销大,并且还有提醒写出来,但我没想到性能开销居然这么大...
于是关掉了 AVIF 转换,只用 WebP 转换也挺香。虽说我知道这个和 CDN 与云存储并不是平替关系,但的确是让我摆脱云存储与 CDN 的途径,以后不出意外的话会长期使用这个方案,感觉挺香的。
现在好像还在用的腾讯云的webp
因为要摆脱第三方云存储、心想两者的目的都是加快访问速度,用第三方云存储是通过厂商强大的集群,自己优化源站减少网络开销,两者都能提高速度,全都拿在自己手里感觉会好一些,当然也是利弊的取舍吧
半年多都不动弹了