这两天上网冲浪的时候,发现了一个叫作「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 格式的图片到图床,本地需要保留两份图片文件。至于本地备份的图片,肯定也是 png 或其他格式的原图优先级更高,毕竟 webp 有用到的话我可以手动再压缩。

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

因此,在发现了「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

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 部署文档

1 中的说明,我们可以自定义这一配置文件,再挂载到容器中去,以对容器进行一些微调。

原始的 config.json 内容如下(如有更新,请参考官方文档):

{ "HOST": "0.0.0.0", "PORT": "3333", "QUALITY": "90", "IMG_PATH": "./pics", "EXHAUST_PATH": "./exhaust", "IMG_MAP": {}, "ALLOWED_TYPES": ["jpg", "png", "jpeg", "bmp", "gif", "svg", "heic", "nef", "webp"], "ENABLE_AVIF": false, "ENABLE_EXTRA_PARAMS": false, "READ_BUFFER_SIZE": 4096, "CONCURRENCY": 262144, "DISABLE_KEEPALIVE": false }

通俗易懂:

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

    2 和示例,这个配置的格式是这么写的:

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

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

  • ALLOWED_TYPES:允许的图片格式。我在测试的时候发现,如果已经是 WebP 格式,程序就会报错。本想向官方提 Issue,但试着在格式中添加了 webp ,程序就不报错了,会直接使用已存在的 WebP 格式图片。(官方已默认添加 webp 格式的图片)

其他部分都没有改动的必要,如果你有需求可以详细参考官方文档自行修改。

修改后的 config.json 保存到本地:

{ "HOST": "0.0.0.0", "PORT": "3333", "QUALITY": "90", "IMG_PATH": "/pic", "EXHAUST_PATH": "./exhaust", "IMG_MAP": { "/anon": "/pics1", "/soyo": "/pics2", "/mygo": "http://example.com" }, "ALLOWED_TYPES": ["jpg", "png", "jpeg", "bmp", "gif", "svg", "heic", "nef", "webp"], "ENABLE_AVIF": false, "ENABLE_EXTRA_PARAMS": false, "READ_BUFFER_SIZE": 4096, "CONCURRENCY": 262144, "DISABLE_KEEPALIVE": 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

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

3

server { listen 443 ssl; http2 on; 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; }

接着,就可以使用 http://example.com/anon/xxx.jpg 访问到 /pics1 路径下名为 xxx.jpg 的图片了。

如果你是将图片保存在博客的 usr/upload 文件夹中,也可以直接反代这一路径:

location /usr/upload { 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'; }

这样就可以在不改变图片链接的前提下使用 WebP Server Go。前提是你已经挂载了博客的 usr/upload 文件夹到 webpgo 中。

使用

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

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

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

然后访问 http://example.com/sina/9b8c9418ly1hbsl6dpurej22fa1i01kx.jpg ,可以直接访问到 https://wx1.sinaimg.cn/large/9b8c9418ly1hbsl6dpurej22fa1i01kx.jpg 的图片!

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

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

然后访问 http://example.com/bili/6d1590d19238188da23755a083eba70f415af569.jpg ,也可以直接访问 https://i0.hdslb.com/bfs/archive/6d1590d19238188da23755a083eba70f415af569.jpg

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

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

或者,如果你认为自己部署一个 WebP Server Go 很麻烦,或是使用纯静态的博客程序托管在 GitHub Pages 上没有服务器,那么可以尝试使用官方的云服务:WebP Cloud Services

打开官网后,点击 Try WebP Cloud 并使用 GitHub 账户授权登录。

登录后,即可来到 WebP Cloud Ser­vices 的控制台。点击屏幕右下方的 Cre­ate Proxy 按钮,创建一个反代配置。

选择一个地区(随便选,国内访问肯定是都慢的),在「Proxy Name」中填入备注用以区分,「Proxy Ori­gin URL」中填入具体到图片路径的原链接。点击 Cre­ate 创建

这样,你就创建好了一个 WebP Cloud Ser­vices 的反代,只需要将 Proxy Ad­dress 提供的地址替换掉你原来的图片地址,就可以啦!

例如,原图片为:https://www.himiku.com/2023/09/21/650b1c28345c7.jpg

那么 WebP Cloud Ser­vices 反代的图片就应为:https://abcdef.webp.ee/2023/09/21/650b1c28345c7.jpg

WebP Cloud Ser­vices 除了国内连接速度可能不太好接受(使用了 Cloud­flare 进行减速),再就是 WebP Cloud Ser­vices 是一个商业项目,其他方面都是要优于自建的。至少不用你准备足够大的硬盘空间来存放转换后的 WebP 图片,也无须担心 WebP Server Go 出 bug 后卡死你的机子了。如果有使用需求的话,就请准备好钱包吧!