我是如何使用 Git 做图床,并使用 hook 实现图片的 WebP 压缩与水印的?
本文最后更新于 2024年11月18日 中午
通常,我们的网站存储空间、网络受限,会将图片和网站分开进行存储和“解耦”,方便后续使用 CDN 加速时,图片和网站可以分开使用不同方案;也方便网站迁移时,只迁移网站本体。
不知道有没有小伙伴想过: 在自己的腾讯云轻量应用服务器上,部署 Git 服务端作为图床仓库,重新定向工作空间到网站目录,并使用 Git hook 实现图片的 WebP 压缩与水印? 这次就给大家浅浅分享一下。
Git
Git 相信大家都不陌生,它是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。Git 由 Linux 之父 Linus 于 2005 年创建,目前由 Git 软件基金会管理。
Git 的核心思想是分布式,推送内容使用 Hash 进行差异化校验,使得 Git 具有更高的可靠性和更快的速度。Git 还支持离线工作,这意味着你可以在没有网络连接的情况下进行开发,然后将其推送到远程仓库。也正是这个特性,使得 Git 成为了一个非常流行的版本控制系统。而我们,也可以使用这些特性,来创建一个图床。
想一想,本地存储图片,之后使用 Git 推送到远程仓库,是不是很方便呢?
如果是写文章,对于一些草稿图片,甚至还可以使用 Git 拉出分支,在文章完成后,合并主分支,统一上线。保持工作台干净,岂不美哉?
graph LR;
A[开始] --> B[本地存储图片/拉取 Git 仓库]
B --> C{是否为草稿图片}
C -->|是| D[创建 Git 分支]
C -->|否| E[推送到远程仓库]
D --> G[合并主分支]
G --> I[发布图片]
E --> I
Bare 裸仓库
平时,我们使用 Git 时,一般会使用工作区,也就是我们平时写代码的地方。
进入.git
目录,就可以看到版本控制区:
但是,我们在服务器上部署的 Git 仓库,不需要工作空间,只需要版本库,用于提供给客户端进行拉取和推送。所以,在服务器上,我们就可以使用裸仓库,作为图床仓库:
1 |
|
hook 钩子
Git 提供了钩子机制,允许我们在 Git 仓库中添加自定义脚本,以在特定事件发生时执行。这些事件包括:提交、推送、合并、拉取等。钩子脚本可以在仓库的 .git/hooks
目录中找到。
我们可以使用这些钩子脚本,来执行一些自定义操作,比如: 重新定向工作空间,以及后续的图片压缩、水印等操作。
裸仓库同样提供了 hook 钩子。比如,我们可以在 hooks/post-receive
中,编写脚本,实现重新定向工作空间:
1 |
|
这样,本地推送图片到服务器上的 Git 裸仓库的流程就是:
sequenceDiagram
participant Local as 本地计算机
participant Server as 腾讯云轻量应用服务器
participant GitRepo as Git 裸仓库
participant WebSite as 网站目录(Nginx)
Local->>Server: 推送图片到 Git 裸仓库
Server->>GitRepo: 接收推送
GitRepo->>Server: 触发 post-receive 钩子
Server->>WebSite: 更新网站目录
既然 hook 是 shell 脚本,那么我们就可以使用 shell 脚本来实现图片的 WebP 压缩与水印了。
其实方法很多,比如: imagemagick
,它是一个功能强大的图片处理工具,支持多种图片格式的转换,以及图片的裁剪、缩放、旋转、水印、滤镜等操作。
但是我更习惯用 python 的 Pillow
库,同样,它是一个强大的图像处理库,支持多种图片格式的转换。
支持创作
制作教程不易,如果热心的小伙伴,想支持创作,可以加入我们的电圈(还可以解锁远程协助、好友位😃):
- Mintimate的电圈: https://afdian.com/a/mintimate
- Mintimate的微信赞赏码 👉 如果认为本教程对你很有帮助,可以请我喝咖啡 ☕
志同道合的小伙伴也是知音难觅。
- 开发者爱好群: 👉 如果你对云服务器、CDN、云数据库和Linux等云计算感兴趣,亦或者喜欢编程、设计、产品、运营等领域,欢迎加入我们的开发者爱好群,一起交流学习(目前可能就我一个人?🤔,毕竟才刚刚创建~)。
当然,也欢迎在B站或YouTube上关注我们:
- Bilibili: https://space.bilibili.com/355567627
- YouTube: https://www.youtube.com/@mintimate/featured
更多:
WebP 格式
WebP 既支持有损压缩也支持无损压缩,相较于 PNG 格式,同样支持透明通道。在质量相同的情况下,WebP 也具有更小的文件体积。
所以,使用 WebP 格式,可以节省很间,进而提高网站内图片的加载速度; WebP 格式也支持渐进式加载,还可以进一步提高用户体验。
操作前提
本文的操作前提,是什么呢?首先是要有一台 Linux 服务器,比如:我就是使用腾讯云的轻量应用服务器。腾讯云的轻量应用服务器(Lighthouse),性能足够强劲。
其实也可以买 腾讯云的云服务器 (CVM) 的,选择 CVM 可以选配更强大的 CPU ,处理 WebP 压缩速度更快。
但是,我测试了一下,我使用的腾讯云轻量应用服务器,CPU 模拟型号是 Intel(R) Xeon(R) Gold 6133 CPU @ 2.50GHz,处理本文的 WebP 并行任务非常足够。
轻量应用服务器长期都有活动,可以进去探索一下:
软件方面,在腾讯云轻量应用服务器上,安装好 Git 和 Python:
1 |
|
与此同时,创建一个 Git 裸仓库,作为图床仓库:
1 |
|
图片转 WebP
如何将图片转成 WebP 格式呢? 前文已经说到,使用 Pillow 库。
Pillow 库支持多种图片格式的转换,包括:JPEG
、PNG
、GIF
、BMP
、TIFF
、PPM
、WebP
等。
按道理我们在腾讯云轻量应用服务器使用的是 Linux 镜像,是可以安装 Linux 的 imagemagick 库的。感兴趣的小伙伴可以尝试一下。
当然,其实你也可以使用存储桶的 WebP 转换功能,比如:腾讯云的 COS 存储桶。
其实我也有用过(大概 2021 年的时候?),改天有机会,给大家介绍一下。
Pillow 库
我们可以很方便地实现图片的 WebP 转换:
1 |
|
添加水印
Pillow 库同样支持添加水印,只需要把水印图片“贴”到目标图片上即可:
1 |
|
一般,水印的位置在图片的下方,并且水印需要设置透明度,在图片的尺寸过小时候,取消水印:
1 |
|
最终的流程就是:
graph LR;
A[开始] --> B[读取原始图像];
B --> C{图像尺寸 >= 512 * 1.5?};
C -->|是| D[添加水印];
C -->|否| E[跳过添加水印];
D --> F[保存为WebP格式];
E --> F;
F --> G[结束];
文章内的图片,就是这样转换的。
Git 差异化文件
Git 作为版本控制工具,可以很方便地实现差异化文件检录,可能平时大家用习惯了 JetBrains、GitHub Desktop 等工具,但是,Git 的命令行强大到可怕。
我们如果要实现两个 commit 的差异化文件,只需要使用 git diff
命令即可:
1 |
|
比如:比较 Hash 值为6abbb89127c806928666b12374dfa013ef95f8b8
和 Hash 值为5fe2590034f4922c427ab74bf948af46c2627d99
的两个 commit 的差异:
是不是有点抽象? 这里我们可以使用类似的命令 git difftree
并追加一下参数:
--no-commit-id
:输出的差异信息中不包含提交 ID;--name-status
:仅显示文件名和状态(如添加、修改、删除等),而不显示具体的差异内容;-r
:递归地比较两个树中的所有子树。
这样的结果就豁然开朗了:
这个时候,如果两次 commit 存在差异,那么可能的输出结果就是:
1 |
|
发现了什么?🤔 没错,我们在 shell 内,可以使用标准化输出的方式,格式化参数文件。
hook 实现
现在,我们看看如何使用 hook 实现自动化部署。首先是工作分区的重定向和参数的定义:
1 |
|
因为,我们提交内容的时候,难免会提交一些无关紧要的文件,比如:表情包、emoji 等,所以,我们需要过滤掉这些文件,并定义需要转换的文件后缀以及需要跳过的文件前缀,配合函数完成逻辑判断:
1 |
|
定义日志输出目录:
1 |
|
之后,标准化我们上文使用 git difftree
命令的输出:
1 |
|
最后,对文件进行二次读取,判断是否需要使用 Python 脚本进行转换:
1 |
|
当然,process_file
函数的实现就比较简单了,直接调用 Python 脚本即可:
1 |
|
需要注意,这里我预留了 action
参数,但是我没有使用。
最终效果
最后,我们来看看效果,经过 commit 和 push 操作推送到我们自己的 Git 仓库之后,进而存储到腾讯云轻量应用服务器 Linux 的硬盘存储内,可以查看日志:
与此同时,我们也可以在 web
目录下查看转换后的图片:
看看转换后的图片和原始图片的大小对比:
同时,本篇文章内的图片,也是使用上述方法转换的,
对于性能的消耗,也是微乎其微的,我们可以在腾讯云轻量应用服务器的后台,看到性能监控曲线:
END
好啦,本篇文章就到这里,感谢阅读。之后的步骤,就看每个人的想法了。比如我就是使用 Nginx 作为反向代理,将转换后的图片直接返回给用户,这样就可以减少服务器的负担了。
有时候也会套一层 CDN,这样就可以加速图片的访问了。
相关代码已经开源,可以访问 https://github.com/Mintimate/GitHookPng2WebP 查看。
最后,制作教程不易,寻找教程也不易,找到志同道合的小伙伴更是知音难觅。如果你对云服务器、CDN、云数据库和Linux等云计算感兴趣,亦或者喜欢编程、设计、产品、运营等领域,欢迎加入我们的开发者爱好群,一起交流学习: 812198734 (目前可能就我一个人?毕竟才刚刚创建 ~)。