mcpField
I
image-optimization-cdn

image-optimization-cdn

github.com/finsilabs开发6099 次安装5 天前更新
代码仓库

关于 image-optimization-cdn

面向电商店铺开发者的图片优化指南,按 Shopify、WooCommerce、BigCommerce 和自定义店铺介绍调整尺寸、现代格式、CDN 与延迟加载。

主要功能

  1. 01按平台选择优化方案
  2. 02调整图片尺寸与格式
  3. 03使用 CDN 分发图片
  4. 04配置响应式图片
  5. 05处理延迟加载与 LCP

适用场景

  1. 01改善商品页图片加载速度
  2. 02为无头店铺搭建图片管线
  3. 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.json
evals/cdn-cache-strategy-and-image-upload-pipe/
criteria.json
task.md
evals/responsive-image-loading-and-lcp-optimiz/
criteria.json
task.md
evals/sharp-pipeline-configuration/
criteria.json
task.md

详细介绍

图片优化 CDN

概述

商品图片通常是电商页面中体积最大的资源,也是导致最大内容绘制(LCP)评分不佳的最大单一因素。经过优化的图片处理流程会将图片调整为所需尺寸,转换为现代格式(WebP、AVIF),使文件体积缩小 30–50%;通过靠近用户的 CDN 进行分发,并对首屏以下的图片应用延迟加载。

何时使用此技能

  • 当商品页面因图片体积过大或未经优化而未通过 Core Web Vitals 检测时(LCP > 2.5s)
  • 为新的无头店面设置图片处理流程时
  • 供应商提供的原始商品图片体积达数 MB,需要自动化处理时
  • 为目前仅提供 JPEG/PNG 的现有店面添加 WebP/AVIF 支持时
  • 测量 Core Web Vitals,且图片是主要瓶颈时

核心说明

步骤 1:确定平台及可用的图片优化方案
平台内置图片 CDN需要执行的操作
ShopifyShopify CDN(Fastly)——自动转换为 WebP,通过 URL 参数调整响应式尺寸在 Liquid 中使用 img_url 筛选器并设置尺寸参数;确保所有 <img> 标签都有 width 和 height 属性;为首屏以下的图片添加 loading="lazy"
WooCommerce默认没有安装 Imagify 或 ShortPixel 插件以自动转换为 WebP;添加 Cloudflare 作为 CDN(免费套餐),实现全球分发
BigCommerceBigCommerce CDN——自动转换为 WebP,调整响应式尺寸BigCommerce 会自动通过 CDN 提供图片;在 URL 中指定图片尺寸,并在模板中为 <img> 设置适当属性,以进行优化
Custom / Headless无——需要自行搭建使用 Cloudinary(托管式)或 Sharp(可自托管)并配合 CDN;参见下方的实现方式
步骤 2:针对平台优化图片

Shopify

Shopify CDN 会自动处理 WebP 转换和尺寸调整。 你需要在 Liquid 模板中正确使用它:

  1. 始终使用带明确尺寸的 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 }}"
/>
  1. 仅对主视觉(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 }}" ... />
  1. 检查 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"。请确认其正常工作:

  1. 查看商品页面的源代码
  2. 确认非首屏图片带有 loading="lazy" 属性
  3. 首屏主图/第一张商品图片应设置为 loading="eager"——在主题模板中进行配置

步骤 4:在 WooCommerce 中设置正确的图片尺寸:

  1. 前往 WooCommerce → 设置 → 产品 → 显示
  2. 将图片尺寸设置为与你的主题实际渲染尺寸一致——过大的图片会浪费带宽
  3. 更改尺寸后,使用 WP CLI 或 Regenerate Thumbnails 插件调整现有图片尺寸:wp media regenerate --only-missing

BigCommerce

BigCommerce 会通过其 CDN 提供所有图片,并为受支持的浏览器自动转换为 WebP。请优化主题模板:

  1. 在 店面 → 我的主题 → 编辑主题文件 中,打开商品页面模板
  2. 使用 getImageSrcset Handlebars 辅助函数生成自适应 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}}"
/>
  1. 在 店面 → 我的主题 → 自定义 中,将图片尺寸设置为与你的设计实际渲染尺寸一致
  2. 对你的商店运行 Google PageSpeed Insights,并处理所有与图片相关的建议

自定义/无头架构

选项 A:Cloudinary(托管式——推荐大多数商店使用)

  1. 在 cloudinary.com 注册(免费套餐:25 GB 存储空间、每月 25 GB 带宽)
  2. 配置你的商店,将商品图片上传到 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,
  });
}
  1. 在商品图片组件中生成自适应 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

评论

支持 Markdown