Cloudflare 适配器图片优化
思路:图片托管到 Cloudflare,边缘转码/裁剪,Astro 输出正确的 src/srcset,既省带宽又提首屏。
为什么要优化图片?
- 图片体积大,原图可达数 MB。
- 终端多样:移动/桌面需要不同尺寸与格式(WebP/AVIF/JPEG)。
- 优化后:更快 LCP、更低流量成本。
Cloudflare Images(推荐)
- 上传原图(仪表盘/CLI/API)。
- 定义 variants(宽高、质量、格式)。
- URL:
https://imagedelivery.net/{hash}/{id}/{variant}。 - Astro 示例:
--- const base = "https://imagedelivery.net/<hash>/<id>"; const variants = [ { name: "thumb", media: "(max-width: 640px)" }, { name: "mid", media: "(max-width: 1024px)" }, { name: "lg", media: "" }, ]; --- <picture> {variants.map((v) => ( <source srcset={`${base}/${v.name}`} media={v.media} /> ))} <img src={`${base}/lg`} alt="demo" loading="lazy" width="1200" height="600" /> </picture>
适配器内置 Image Service
- compile:构建期转码,产物含优化图;首访快但构建时间/体积增大。
- passthrough:运行时按需转码,构建快体积小;首访需转码,依赖 Cloudflare 运行时。
配置 passthrough:
import cloudflare from "@astrojs/cloudflare";
import { defineConfig } from "astro/config";
export default defineConfig({
adapter: cloudflare({
imageService: { service: "cloudflare", config: { mode: "passthrough" } },
}),
});
边缘 Function 变换(对象存储场景)
- 已有 S3/OSS:在 Pages Functions/Workers 拉取原图并用
image resizing转码。 - URL 形如
/img?w=800&fmt=webp&url=https://bucket/xxx.jpg。 - 为转码结果设长缓存;原图可更长缓存。
Astro 端实践
<img>+srcset/sizes;@astrojs/image亦可,但直接写 srcset 最轻。- 补
width/height或aspect-ratio避免 CLS;加loading="lazy"、decoding="async"。 - 背景图用多尺寸/媒体查询,避免一张大图通吃。
品质与格式
- 优先 WebP/AVIF,必要时回退 JPEG/PNG。
- 质量 70–85 常用;矢量用 SVG。
排障清单
- 404:variant/路径不匹配。
- 首访慢:passthrough 首次转码正常,可预热或切 compile。
- 色偏/花屏:检查质量/格式参数与色彩空间。
- 体积大:降低质量、增加尺寸档位。
- CLS:补 width/height。
为什么需要图片优化?
现代网站通常包含大量图片资源,这些图片可能:
- 文件体积大:未优化的图片可能达到几 MB,严重影响加载速度
- 格式不统一:不同设备需要不同格式(WebP、AVIF 、JPEG)
- 尺寸不匹配:同一张图片在不同场景需要不同尺寸
通过 Cloudflare 的图片优化服务,可以:
- 自动转换图片格式(WebP、AVIF)
- 按需调整图片尺寸
- 压缩图片质量
- 利用 CDN 缓存加速
配置 Cloudflare 图片服务
在 astro.config.mjs 中配置 Cloudflare 适配器时,可以启用图片优化服务:
import HeadingWithIconH2 from '@/components/mdx/HeadingWithIconH2.astro';
export const components = {
h2: HeadingWithIconH2,
};
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
adapter: cloudflare({
// 启用平台代理,在本地模拟 Cloudflare 的环境
platformProxy: {
enabled: true,
experimental: {
remoteBindings: true,
},
},
// 启用 Cloudflare 图片服务
imageService: 'cloudflare',
}),
});
两种图片处理模式
Cloudflare 适配器提供了两种图片处理模式,各有优缺点:
1. Compile 模式(编译时处理)
工作原理:
- 在构建时处理所有图片
- 生成优化后的图片文件到
dist/_astro目录 - 构建后的网站包含已优化的图片
配置方式:
adapter: cloudflare({
imageService: 'cloudflare',
// 默认使用 compile 模式
}),
特点:
- ✅ 构建后图片已优化,无需运行时处理
- ✅ 首次访问即可获得优化后的图片
- ❌ 构建时间较长(需要处理所有图片)
- ❌ 构建产物体积较大(包含所有优化后的图片)
适用场景:
- 图片数量较少
- 构建时间不是主要考虑因素
- 需要完全控制图片优化过程
2. Passthrough 模式(运行时处理)
工作原理:
- 构建时跳过图片处理,保留原始图片
- 运行时由 Cloudflare 的 Images Transformations 服务处理
- 首次请求时进行转换并缓存
配置方式:
adapter: cloudflare({
imageService: {
service: 'cloudflare',
config: {
// 使用 passthrough 模式
mode: 'passthrough',
},
},
}),
特点:
- ✅ 构建时间短(不处理图片)
- ✅ 构建产物体积小(只包含原图)
- ✅ 按需优化,节省资源
- ❌ 首次访问需要转换时间
- ❌ 依赖 Cloudflare 的 Images Transformations 服务(非完全免费)
实际效果:
使用 passthrough 模式后,HTML 中的图片地址会自动转换为:
<!-- 原始地址 -->
<img src="/images/hero.jpg" alt="Hero">
<!-- 转换后的地址 -->
<img src="/cdn-cgi/image/onerror=redirect,width=1024,height=682,format=webp/_astro/hero.jpg" alt="Hero">
缓存机制:
- 首次请求:响应头中
cf-cache-status: MISS(此时对原始图片进行了转换并存储到缓存) - 后续请求:响应头中
cf-cache-status: HIT(直接从缓存返回)
在 Cloudflare 控制台配置
要使用 passthrough 模式,需要在 Cloudflare 控制台启用 Images Transformations 服务:
- 登录 Cloudflare Dashboard
- 选择你的域名
- 进入 媒体 → Images → Transformations
- 启用 Images Transformations 服务
注意事项:
- 这个服务不是完全免费的
- 免费套餐有使用限制
- 超出限制后会产生费用
使用 Astro Image 组件
在 Astro 中使用图片时,推荐使用 Image 组件:
---
import { Image } from 'astro:assets';
import heroImage from '../assets/hero.jpg';
---
<Image
src={heroImage}
alt="Hero image"
width={1024}
height={682}
format="webp"
quality={80}
/>
组件属性:
src:图片源文件(使用 import 导入)alt:图片描述文本width/height:图片尺寸format:目标格式(webp、avif、jpeg 等)quality:图片质量(1-100)
实际效果对比
Compile 模式
# 构建过程
npm run build
# 构建时间:较长(需要处理所有图片)
# dist/_astro 目录:包含优化后的图片
# 文件大小:较大(包含所有优化版本)
构建产物:
dist/
└── _astro/
├── hero.webp # 优化后的图片
├── product1.webp
└── product2.webp
Passthrough 模式
# 构建过程
npm run build
# 构建时间:较短(不处理图片)
# dist/_astro 目录:只包含原始图片
# 文件大小:较小(只包含原图)
构建产物:
dist/
└── _astro/
├── hero.jpg # 原始图片
├── product1.jpg
└── product2.jpg
运行时转换:
- 首次访问:Cloudflare 自动转换并缓存
- 后续访问:直接从缓存返回
性能监控
可以通过浏览器开发者工具监控图片优化效果:
1. 检查响应头
在 Network 面板中查看图片请求的响应头:
cf-cache-status: HIT # 缓存命中
cf-polished: 1 # 已优化
content-type: image/webp # 格式转换
2. 对比文件大小
// 原始图片大小
Original: 2.5 MB (JPEG)
// 优化后大小
Optimized: 180 KB (WebP)
// 压缩率:92.8%
3. 加载时间对比
- 未优化:2.5 MB,加载时间 ~3.5s(3G 网络)
- 优化后:180 KB,加载时间 ~0.5s(3G 网络)
最佳实践
1. 选择合适的模式
- 小型项目:使用 compile 模式,构建时优化所有图片
- 大型项目:使用 passthrough 模式,按需优化,节省构建时间
- 图片数量多:推荐 passthrough 模式
2. 图片格式选择
---
// 优先使用现代格式
<Image
src={image}
format="webp" // 或 "avif"
quality={80} // 平衡质量和文件大小
/>
3. 响应式图片
---
<Image
src={image}
alt="Responsive image"
widths={[400, 800, 1200]}
sizes="(max-width: 768px) 100vw, 50vw"
/>
4. 懒加载
---
<Image
src={image}
alt="Lazy loaded image"
loading="lazy"
/>
5. 监控和优化
- 定期检查 Cloudflare 控制台的使用情况
- 监控图片加载性能
- 根据实际使用情况调整配置
常见问题
Q1: 两种模式的实际效果有什么区别?
两种模式在最终用户体验上基本一致,主要区别在于:
- 构建时间:compile 模式较长,passthrough 模式较短
- 构建产物:compile 模式包含优化图片,passthrough 模式只包含原图
- 首次访问:passthrough 模式可能需要转换时间
Q2: 如何选择使用哪种模式?
- 如果图片数量少(< 50 张),使用 compile 模式
- 如果图片数量多(> 50 张),使用 passthrough 模式
- 如果构建时间敏感,使用 passthrough 模式
Q3: passthrough 模式的费用如何?
- Cloudflare Images Transformations 有免费额度
- 超出免费额度后按使用量计费
- 具体费用请查看 Cloudflare 官方定价
Q4: 本地开发时图片会优化吗?
使用 platformProxy 配置后,本地开发环境会模拟 Cloudflare 的行为,但图片优化效果可能与生产环境略有不同。
总结
通过合理配置 Cloudflare 适配器的图片优化服务,可以:
- 显著提升性能:自动转换格式、调整尺寸、压缩质量
- 简化开发流程:无需手动处理图片优化
- 利用 CDN 缓存:优化后的图片自动缓存,加速访问
选择适合你项目的模式,平衡构建时间和运行时性能,让你的 Astro 网站在 Cloudflare 上运行得更快、更高效。