关于 image-optimization-cdn
面向电商店铺开发者的图片优化指南,按 Shopify、WooCommerce、BigCommerce 和自定义店铺介绍调整尺寸、现代格式、CDN 与延迟加载。
主要功能
- 01按平台选择优化方案
- 02调整图片尺寸与格式
- 03使用 CDN 分发图片
- 04配置响应式图片
- 05处理延迟加载与 LCP
适用场景
- 01改善商品页图片加载速度
- 02为无头店铺搭建图片管线
- 03为 JPEG/PNG 店铺增加 WebP 支持
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ finsilabs/ awesome-ecommerce-skills --skill image-optimization-cdn安装后在 Claude Code 中输入/image-optimization-cdn确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
tile.jsonevals/cdn-cache-strategy-and-image-upload-pipe/criteria.jsontask.mdevals/responsive-image-loading-and-lcp-optimiz/criteria.jsontask.mdevals/sharp-pipeline-configuration/criteria.jsontask.md详细介绍
图片优化 CDN
概述
商品图片通常是电商页面中体积最大的资源,也是导致最大内容绘制(LCP)评分不佳的最大单一因素。经过优化的图片处理流程会将图片调整为所需尺寸,转换为现代格式(WebP、AVIF),使文件体积缩小 30–50%;通过靠近用户的 CDN 进行分发,并对首屏以下的图片应用延迟加载。
何时使用此技能
- 当商品页面因图片体积过大或未经优化而未通过 Core Web Vitals 检测时(LCP > 2.5s)
- 为新的无头店面设置图片处理流程时
- 供应商提供的原始商品图片体积达数 MB,需要自动化处理时
- 为目前仅提供 JPEG/PNG 的现有店面添加 WebP/AVIF 支持时
- 测量 Core Web Vitals,且图片是主要瓶颈时
核心说明
步骤 1:确定平台及可用的图片优化方案
| 平台 | 内置图片 CDN | 需要执行的操作 |
|---|---|---|
| Shopify | Shopify CDN(Fastly)——自动转换为 WebP,通过 URL 参数调整响应式尺寸 | 在 Liquid 中使用 img_url 筛选器并设置尺寸参数;确保所有 <img> 标签都有 width 和 height 属性;为首屏以下的图片添加 loading="lazy" |
| WooCommerce | 默认没有 | 安装 Imagify 或 ShortPixel 插件以自动转换为 WebP;添加 Cloudflare 作为 CDN(免费套餐),实现全球分发 |
| BigCommerce | BigCommerce CDN——自动转换为 WebP,调整响应式尺寸 | BigCommerce 会自动通过 CDN 提供图片;在 URL 中指定图片尺寸,并在模板中为 <img> 设置适当属性,以进行优化 |
| Custom / Headless | 无——需要自行搭建 | 使用 Cloudinary(托管式)或 Sharp(可自托管)并配合 CDN;参见下方的实现方式 |
步骤 2:针对平台优化图片
Shopify
Shopify CDN 会自动处理 WebP 转换和尺寸调整。 你需要在 Liquid 模板中正确使用它:
- 始终使用带明确尺寸的
image_url筛选器:
<img
src="{{ product.featured_image | image_url: width: 800 }}"
srcset="{{ product.featured_image | image_url: width: 400 }} 400w,
{{ product.featured_image | image_url: width: 800 }} 800w,
{{ product.featured_image | image_url: width: 1200 }} 1200w"
sizes="(max-width: 640px) 100vw, 50vw"
width="800" height="800"
loading="lazy"
alt="{{ product.featured_image.alt | escape }}"
/>
- 仅对主视觉(LCP)图片使用
loading="eager":
{% if forloop.first %}
{%- assign loading = 'eager' -%}
{%- assign fetchpriority = 'high' -%}
{% else %}
{%- assign loading = 'lazy' -%}
{%- assign fetchpriority = 'auto' -%}
{% endif %}
<img loading="{{ loading }}" fetchpriority="{{ fetchpriority }}" ... />
- 检查 LCP 评分:
- 在 Shopify 管理后台中,前往 Online Store → Themes,然后点击 View report
- 或在商品页面和系列页面上运行 Google PageSpeed Insights(pagespeed.web.dev)
- 移动设备上的评分低于 75,通常意味着主视觉图片需要设置
fetchpriority="high",或图片体积过大
WooCommerce
默认情况下,WooCommerce 会直接从你的服务器提供图片,不使用 CDN,也不会转换为 WebP。需要完成以下步骤:
步骤 1:添加 WebP 转换(任选其一):
- Imagify(免费套餐:每月 25 MB):从 WordPress.org 安装,前往 媒体 → Imagify,运行批量优化向导——它会将所有现有图片转换为 WebP,并为新上传的图片启用自动转换
- ShortPixel(免费套餐:每月 100 个积分):流程类似;安装为插件,并在上传时转换图片
步骤 2:添加 CDN 分发:
- Cloudflare(免费):将域名添加到 Cloudflare 后,所有图片(及其他资源)都会自动通过 Cloudflare 的 300 多个全球边缘节点提供
- BunnyCDN(每 TB 1 美元):更灵活;对于高流量商店,性能优于免费的 Cloudflare;使用 BunnyCDN WordPress 插件进行配置
步骤 3:配置延迟加载(WordPress 5.5+ 会自动处理):
从 5.5 版开始,WordPress 会自动为所有 <img> 标签添加 loading="lazy"。请确认其正常工作:
- 查看商品页面的源代码
- 确认非首屏图片带有
loading="lazy"属性 - 首屏主图/第一张商品图片应设置为
loading="eager"——在主题模板中进行配置
步骤 4:在 WooCommerce 中设置正确的图片尺寸:
- 前往 WooCommerce → 设置 → 产品 → 显示
- 将图片尺寸设置为与你的主题实际渲染尺寸一致——过大的图片会浪费带宽
- 更改尺寸后,使用 WP CLI 或 Regenerate Thumbnails 插件调整现有图片尺寸:
wp media regenerate --only-missing
BigCommerce
BigCommerce 会通过其 CDN 提供所有图片,并为受支持的浏览器自动转换为 WebP。请优化主题模板:
- 在 店面 → 我的主题 → 编辑主题文件 中,打开商品页面模板
- 使用
getImageSrcsetHandlebars 辅助函数生成自适应srcset属性:
<img
src="{{getImage image 'product_size'}}"
srcset="{{getImageSrcset image 1x='product_size' 2x='zoom_size'}}"
loading="lazy"
width="800" height="800"
alt="{{image.alt}}"
/>
- 在 店面 → 我的主题 → 自定义 中,将图片尺寸设置为与你的设计实际渲染尺寸一致
- 对你的商店运行 Google PageSpeed Insights,并处理所有与图片相关的建议
自定义/无头架构
选项 A:Cloudinary(托管式——推荐大多数商店使用)
- 在 cloudinary.com 注册(免费套餐:25 GB 存储空间、每月 25 GB 带宽)
- 配置你的商店,将商品图片上传到 Cloudinary:
// lib/cloudinary.js
import { v2 as cloudinary } from 'cloudinary';
cloudinary.config({ cloud_name: process.env.CLOUDINARY_CLOUD_NAME, api_key: ..., api_secret: ... });
export function getProductImageUrl(publicId, { width, height }) {
return cloudinary.url(publicId, {
transformation: [{
width, height, crop: 'fill', gravity: 'auto',
quality: 'auto:good',
fetch_format: 'auto', // Auto-serves WebP/AVIF based on Accept header
}],
secure: true,
});
}
- 在商品图片组件中生成自适应
srcset:
export function ProductImage({ publicId, alt, priority = false }) {
const widths = [240, 400, 600, 800, 1200];
const srcSet = widths.map(w => `${getProductImageUrl(publicId, { width: w, height: w })} ${w}w`).join(', ');
return (
<img
src={getProductImageUrl(publicId, { width: 400, height: 400 })}
srcSet={srcSet}
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 25vw"
alt={alt}
width={400} height={400}
loading={priority ? 'eager' : 'lazy'}
fetchPriority={priority ? 'high' : 'auto'}
/>
);
}
选项 B:Sharp(自托管图片处理)
使用 Sharp 构建自托管处理管线。在上传时处理图片,并将不同尺寸的图片存储在对象存储中(S3、R2、Backblaze):
// lib/image-processor.js
import sharp from 'sharp';
const SIZES = {
thumbnail: { width: 240, height: 240 },
card: { width: 400, height: 400 },
detail: { width: 800, height: 800 },
zoom: { width: 1600, height: 1600 },
};
export async function processAndStoreProductImage(inputBuffer, productId) {
const urls = {};
for (const [sizeName, dims] of Object.entries(SIZES)) {
const webpBuffer = await sharp(inputBuffer)
.rotate() // auto-rotate from EXIF
.resize({ ...dims, fit: 'cover', withoutEnlargement: true })
.webp({ quality: 80 })
.toBuffer();
const key = `products/${productId}/${sizeName}.webp`;
await uploadToStorage(key, webpBuffer, 'image/webp');
urls[sizeName] = `https://images.yourstore.com/${key}`;
}
return urls;
}
使用不可变 CDN 标头提供图片(在文件名中加入内容哈希,以便更新缓存):
// Image URL response headers
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
最佳实践
- 为所有
<img>标签明确设置width和height——这会预留图片加载所需的空间,防止累积布局偏移(CLS) - 仅为 LCP 图片使用
loading="eager"和fetchpriority="high"——对所有图片应用eager会破坏延迟加载,并增加页面初始体积 - 切勿放大图片——在 400px 容器中提供 2000px 图片会浪费带宽;在 Sharp 中使用
withoutEnlargement: true,或使用 Cloudinary 的宽度/高度参数 - 通过 URL 版本控制清除 CDN 缓存——在图片文件名中加入内容哈希或版本号;更改 URL 比手动清除 CDN 缓存更可靠
- 使用真实用户监控(RUM)监测生产环境中的 LCP——实验室测试(Lighthouse)会在缓存干净的情况下测量 LCP;RUM 则会捕获实际用户体验
常见问题
| 问题 | 解决方案 |
|---|---|
| LCP 图片不是你预期的那张 | 使用 Chrome DevTools → Performance 标签页,找出实际的 LCP 元素;它可能是背景图片或主视觉横幅,而非商品图片 |
| 按需转换时 AVIF 编码太慢 | 上传时预先生成 AVIF;实时转换时使用 WebP(编码速度比 AVIF 快 50 倍) |
| 生产环境缺少 Sharp 原生二进制文件 | 将 sharp 添加到 dependencies(而非 devDependencies);对于 Docker 构建,请匹配目标架构:npm install --platform=linux --arch=x64 sharp |
| CDN 图片首次请求时无法加载 | 上传后,获取热门商品图片的 CDN URL 以预热缓存;不要依赖首位访客来预热缓存 |
| WooCommerce 图片无法转换为 WebP | 确认主机支持 GD 或 Imagick PHP 扩展(Imagify/ShortPixel 都需要这两个扩展);如果不支持,请联系主机服务商 |
相关技能
- @ecommerce-caching
- @edge-commerce
- @monitoring-alerting-commerce
- @responsive-storefront