这两天上网冲浪的时候,发现了一个叫作「WebP Server Go」的开源项目。

这个项目是这么介绍的:

Go ver­sion of WebP Server. A tool that will serve your JPG/​PNG/​BMP/​SVGs as WebP/​AVIF for­mat with com­pres­sion, on-the-fly.

WebP Server 的 Go 版本,旨在将您的 JPG/​PNG/​BMP/​SVG 图片进行动态压缩并转换为 WebP/​AVIF 格式。

简单地说,就是一个自动压缩图片为 WebP/​AVIF 格式的工具。

关于 WebP 这一格式,早在《Mikusa Yearly Issue 1》一文中我就有详细地解释过。当时为了节省 CDN 流量的开销,拜托 Z 酱帮我写了判断用来自动调用同路径下的 WebP 图片,唯一的不足就是要手动压缩图片并上传到服务器。后来 VOID 更新,我便放弃了这个需要更改主题代码的方案,改为直接使用 WebP 格式的图片。缺点也很明显,我需要手动压缩原始图片,再上传 WebP 格式的图片到图床,本地需要保留两份图片文件。

用「WebP Server Go」优化你的图片

其实写东西的时候顺带压缩下图片花不了多少时间,可就是会一转眼就忘记压缩直接上传原图。不管不顾还好,强迫症发作的时候就会想着删掉原图重新上传。看起来是不痛不痒的问题,但也有会感到烦躁的时候。

因此,在发现了「WebP Server Go」之后,我便急忙部署在服务器上运行起来,测试实际的使用效果。

安装

项目提供了 Docker 容器,使用 docker com­pose 就可以一键安装:

version: "3.9"
services:

webpgo:
image: webpsh/webp-server-go
environment:
- MALLOC_ARENA_MAX=1
volumes:
- ./pic:/opt/pics #本地图片路径
- ./webpgo/exhaust:/opt/exhaust #压缩后的图片缓存
- ./webpgo/metadata:/opt/metadata #压缩前后的图片元数据缓存
ports:
- 3333:3333
restart: unless-stopped
container_name: webpgo
deploy:
resources:
limits:
memory: 400M
memswap_limit: 400M

在 volumes 挂载目录中,./pic 指的是本地存放图片的路径,需要挂载到容器中的 /opt/pics 文件夹中。假设你有张图片路径为 ./pic/myblog/test.png ,那么 WebP Server Go 压缩后的链接就是 http://example.com/myblog/test.png 。

/opt/pics 、/opt/exhaust 、/opt/metadata 是配置文件 config.json 中的默认配置,并非不可修改。参考官方 Docker 部署文档 中的说明,我们可以自定义这一配置文件,再挂载到容器中去,以对容器进行一些微调。

原始的 config.json 内容如下:

{
"HOST": "0.0.0.0",
"PORT": "3333",
"QUALITY": "80",
"IMG_PATH": "/opt/pics",
"IMG_MAP": {},
"EXHAUST_PATH": "./exhaust",
"ALLOWED_TYPES": ["jpg","png","jpeg","bmp","gif","svg","heic"],
"ENABLE_AVIF": false,
"ENABLE_EXTRA_PARAMS": false
}

通俗易懂:

QUALITY:压缩质量,默认 80,即 80%,有需要可以修改为 90%。
IMG_PATH:图片路径,即映射中的 /opt/pics,你也可以修改为 ./pic,只是修改完后不要忘了同时修改 docker-compose.yml 文件。这一配置项亦支持远程路径,即你可以填写 http://example.com 直接从远程链接里抓图,这样就不用本地挂载图片了。
IMG_MAP:多路径。按照官方的解释 和示例,这个配置的格式是这么写的:

"IMG_MAP": {
"/anon": "/pics1",
"/soyo": "/pics2",
"/mygo": "http://example.com"
},

简单地说,: 左边填你想要展示的路径,随便什么都行只要格式是 /xxx;右边填具体路径 ./pics1 或远程链接 http://example.com ,多路径就生效了。只不过要注意的是,链接的格式必须为 http?s://.*,不匹配此格式的会被忽略。

ALLOWED_TYPES:允许的图片格式。我在测试的时候发现,如果已经是 WebP 格式,程序就会报错。本想向官方提 Issue,但试着在格式中添加了 webp ,程序就不报错了,会直接使用已存在的 WebP 格式图片。
其他部分都没有改动的必要,修改后的 config.json 保存到本地:

{
"HOST": "0.0.0.0",
"PORT": "3333",
"QUALITY": "90",
"IMG_PATH": "/pic",
"IMG_MAP": {
"/anon": "/pics1",
"/soyo": "/pics2",
"/mygo": "http://example.com"
},
"EXHAUST_PATH": "./exhaust",
"ALLOWED_TYPES": ["jpg","png","jpeg","bmp","gif","svg","webp","heic"],
"ENABLE_AVIF": false,
"ENABLE_EXTRA_PARAMS": false
}

再挂载到容器内部即可。

于是,docker-compose.yml 也跟着改动:

version: "3.9"
services:

webpgo:
image: webpsh/webp-server-go
environment:
- MALLOC_ARENA_MAX=1
volumes:
- ./webpgo/config.json:/etc/config.json #配置文件,需提前创建
- ./pics:/pics #本地图片路径
- ./pics1:/pics1 #本地图片路径1
- ./pics2:/pics2 #本地图片路径2
- ./webpgo/exhaust:/opt/exhaust #压缩后的图片缓存
- ./webpgo/metadata:/opt/metadata #压缩前后的图片元数据缓存
ports:
- 3333:3333
restart: unless-stopped
container_name: webpgo
deploy:
resources:
limits:
memory: 400M
memswap_limit: 400M

安装完毕后,可以使用 Ng­inx 进行反代 :

server {
listen 443 ssl http2;
server_name example.com;

省略SSL配置

location / {
proxy_pass http://webpgo: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';
}
access_log /home/wwwlogs/example.com.log;
}

注释掉的是一段禁用缓存的配置。鉴于自用需要缓存,所以注释掉。

使用

其实安装完就可以直接开始使用了,没什么好写的东西了。但我测试时发现,这玩意可以拿来反代任意图片,不受防盗链影响,比如 sina。

例如在 IMG_MAP 配置中写成这样:

"IMG_MAP": {
"/sina": "https://wx1.sinaimg.cn/large"
},

然后访问 http://example.com/sina/9b8c9418ly1hbsl6dpurej22fa1i01kx.jpg ,可以直接用!

或者是 bili­bili 的视频封面:

"IMG_MAP": {
"/bili": "https://i0.hdslb.com/bfs/archive"
},

然后访问 http://example.com/bili/6d1590d19238188da23755a083eba70f415af569.jpg ,也可以直接用!

也就是说,WebP Server Go 不仅能拿来压缩图片,还能当便捷反向(图片)代理使用!

只要服务器能下载到图片!

不过,使用 WebP Server Go 唯一的代价,就是需要你有足够大的硬盘空间来存放转换后的 WebP 图片。这大概是比较不能接受的缺点吧。

哦对了, WebP Server Go 还有个内存泄漏的 Bug 还没修掉,所以启动容器前需要加上内存限制的配置才行(文章里的配置已经加上了)。

https://docs.webp.sh/usage/usage/ ↩
https://docs.webp.sh/usage/multipath/ ↩
参考官方配置:https://docs.webp.sh/usage/usage-with-binary/ ↩