squeeze+Cloudflare R2实现博客图片压缩和加载优化
对于博客的图片管理这一块我之前一直做得比较随意,但前两天回看我的文章时发现加载速度惊人地慢…然后我就想起来:我的图片好像都是原图上传的!一篇文章加载几十MB的图片谁来都顶不住啊,于是赶紧把图片优化提上日程。
背景介绍
我原来的做法很简单:写作使用Typora,通过设置和PicGo联动,在PicGo设置Github图床,然后设一个二级域名(比如cdn.cybereal.one) 用CNAME解析到一个jsDelivr的国内镜像,这样基本不用我做什么设置,在编辑器里传一张图就可以之间转为cdn,cyebreal.one开头的网址了。
但这样做有两个问题:一个是我原图上传毫无压缩,这在互联网内容传输是非常错误的选择,因为在网页浏览中一张10MB的原图可能和压缩后300KB的图片观感差异并不太大,但对加载速度的影响是极为显著的,以前看过这么一段话:
网站加载时间每多一秒,将严重损害业务表现。根据多项研究,每增加1秒延迟:转化率会减少7%,页面浏览量减少11%,用户满意度下降16%,甚至会导致10%的用户流失。加载时间超过3秒,可能导致超过53%的移动用户跳出。
虽然个人网站也不是特别在意用户流失(本来也没多少浏览量),但加载速度太慢无论如何都还是很不方便。
此外,原来用的cdn是我在网上随便找的jsDelivr镜像,加载速度和可靠性都不是很有保证。
于是打算在上传前加一个压缩的预处理,以及换一个CDN,研究一番决定使用Cloudflare R2存储桶。
图片压缩
既然之前上传图片的工作流用到了PicGo,它也有丰富的插件生态,那么事情就很好办了。一番搜寻之后我找到了picgo-plugin-squeeze这个插件,它支持本地压缩和在线压缩两种模式,本地使用npm包sharp实现,在线压缩使用色彩笔(昨天我下插件时还是这样,但今天一看作者又更新了一个TinyPNG的在线方案)
这个插件其实功能很完善,该有的都有,但我还希望有两个功能:一个是格式转换,比如压缩的同时把jpg转webp之类的(作者已经更新了),还有自定义分辨率,比如4k的图压一下顺便转1080p,因为想加这两个功能,晚上用codex写了一个小时,但各种原因装不到PicGo里…遂放弃
于是就直接使用这个插件了,图片质量我设为75,其实压缩效果还是不错的,游戏截图可以压缩92%左右


于是图片优化的部分就结束了,很简单,就在PicGo装个插件的事
Cloudflare R2
接下来是更换CDN,本来想着换到国内的某些对象存储,比如腾讯云,七牛云OSS之类的,后来看到网上说R2不收流量费,还有免费额度,正好我域名也是托管在CF的,比较方便,就选这个了
第一阶段:在 Cloudflare 创建 R2 存储桶与获取凭证
首先登陆Cloudflare ,接着选择R2对象存储,第一次打开会需要激活R2的计划,要绑个银行卡之类的,不过只要用量不超过A类操作(上传写入之类的)100万次/月和B类操作(读取等)1000万次/月,以及每月10GB限额,就不会收费,如果没有银行卡参照这期文章或者docofcard

创建存储桶 (Bucket)
- 点击“创建存储桶” (Create Bucket)。
- 名称:起一个你喜欢的名字(比如
my-blog-images)。 - 位置提示:默认“自动”即可(Cloudflare 会根据上传源自动分配,通常会在亚太地区)。
- 创建完成后,你会在存储桶概览里看到一个类似于
https://<你的账户ID>.r2.cloudflarestorage.com的 S3 终结点 (Endpoint) 链接,把它复制下来备用。 
获取 API 令牌 (核心钥匙)
- 回到 R2 的主界面(不要进具体的存储桶),在右上角或者右侧边栏找到 “管理 R2 API 令牌”。
- 点击“创建 API 令牌”。
- 权限:务必选择 “对象读和写”。
- 指定存储桶:强烈建议只勾选你刚才创建的那个博客专属 Bucket,遵循最小权限原则。
- TTL:选择“永久”。
- 创建后,页面会仅显示一次你的秘钥信息。请立刻将 访问密钥 ID (Access Key ID) 和 机密访问密钥 (Secret Access Key) 复制并妥善保存。
第二阶段:绑定自定义域名(关键步骤)
R2 默认会提供一个 *.r2.dev 的公共访问链接,但这个链接经常被墙,且有速率限制。既然你有自己的域名并且托管在 Cloudflare 上,直接绑定自定义域名才是完全体。
- 进入你刚才创建的存储桶设置页面。
- 找到 “公共访问” (Public Access) -> **“自定义域” (Custom Domains)**。
- 点击“连接域”,输入你规划好的图片二级域名(例如
cdn.你的域名.com)。 - Cloudflare 会自动在你的 DNS 记录里添加对应的 CNAME 记录,并自动配置 SSL 证书。
- 等待几分钟,直到状态显示为“活跃 (Active)”。你的图片访问基础 URL 就是
[https://cdn.你的域名.com](https://cdn.你的域名.com)了。 
第三阶段:打通 PicGo 链路
因为 R2 完美兼容亚马逊 S3 协议,所以我们不需要找专门的 R2 插件,直接用最成熟的 S3 插件即可。
- 安装插件 在 PicGo 的插件设置里,搜索并安装
picgo-plugin-s3(认准作者是 wayjam 的那个版本,下载量最高)。 - 配置 S3 图床参数 进入图床设置 -> 亚马逊 S3,按照以下规则填写:
- 应用密钥 ID:填入第一阶段获取的 Access Key ID。
- 应用密钥:填入第一阶段获取的 Secret Access Key。
- 桶名:填入你的存储桶名称(例如
my-blog-images)。 - 上传文件路径:可以写
{year}/{month}/{fileName},这样云端文件会自动按年月归档。 - 地区:填
auto或者直接留空。 - 自定义节点:填入第一阶段获取的 S3 终结点,类似于
https://<账户ID>.r2.cloudflarestorage.com。 - 自定义域名:填入第二阶段绑定的域名,例如
[https://cdn.你的域名.com](https://cdn.你的域名.com)。 - ForcePathStyle:开启(设为
true或勾选)。这是兼容第三方 S3 服务的关键开关。 - RejectUnauthorized:关闭(设为
false,避免某些本地证书校验问题)。 - ACL 访问控制列表:
public-read
- 设为默认图床 保存配置,并将其设为默认图床。


结束!
如果不出问题的话,做完这两步,配合Typora联动PicGo,就可以实现向Typora粘贴图片→自动通过PicGo上传图片→压缩图片→传到R2存储桶→自动返回链接的模式了,大幅减少网站加载速度,收工!