agentsclimarketplace

Nextjs cloudflare image loader

Skill hifizz/skills/skills/nextjs-cloudflare-image-loader

zilin 的个人 Agent Skills 库,真实在用的开发能力,可被 Claude Code / Cursor 等 50+ agent 自动发现安装

Install
npx -y skills add hifizz/skills --skill nextjs-cloudflare-image-loader

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

用 Cloudflare Image Transformations(/cdn-cgi/image + R2/自有域名)替代 Vercel 图片优化,给 Next.js 配置 custom loader,保留 next/image 全部能力(srcset/lazy/priority/CLS 防抖)同时把图片流量成本降为零。当用户提到 Vercel 图片优化太贵、Image Optimization 超额、Cloudflare 图片裁剪/缩放、/cdn-cgi/image、R2 图片优化、custom image loader、图片 CDN 省钱,或想在 Cloudflare 上做响应式图片时使用。

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

6.6 KB, ~2.0k tokens by cl100k_base, as published. Nobody here has run it

把 Next.js 的图片优化从 Vercel(或自建 sharp)切到 Cloudflare Image Transformations:一个 10 行的 custom loader + 一段 next.config 配置。装完后:

  • <Image> 组件照常用,srcset / lazy loading / priority / CLS 防抖全部保留——只是 URL 变成 https://media.example.com/cdn-cgi/image/width=828,quality=75,format=auto/…
  • 图片字节从 Cloudflare 边缘出,egress $0(这才是省钱的大头,见下方计费模型)
  • 变体基数被 deviceSizes 网格锁死,不会因为参数组合爆炸吃穿 5,000 免费转换额度

反模式先行:不要这样做

很多项目(包括本 skill 的来源项目最初版本)的做法是 images: { unoptimized: true } + 自写 <OptimizedImage> 组件手拼 /cdn-cgi/image/ URL 和 srcset。这是错的

  1. 放弃了 next/image 的 lazy/priority/sizes/CLS 防抖,全部要手工重造(约 200 行组件替代 10 行 loader)
  2. 手拼参数容易把 height/fit/gravity 全塞进 URL → 每个「源图 × 参数组合」是一次计费 unique transformation,变体基数失控
  3. Cloudflare 官方机制就是 next/image custom loader,不要绕开它

安装步骤

Step 1 — Cloudflare 侧前提(一次性,必须全过)

  1. 图片所在域名是你自己 zone 上的自定义域名(R2 桶绑自定义域名即可)。pub-*.r2.dev 开发域名不支持 transformations。
  2. Dashboard → Images → Transformations → 对该 zone 点击 Enable。没开这一步,/cdn-cgi/image/ 返回 404。
  3. 如果 Next.js 应用域名和图片域名不在同一个 zone:开启该 zone 的 "Resize images from any origin"(否则跨 zone 引用被拒)。

Step 2 — 复制模板

模板目标位置说明
templates/image-loader.ts项目根目录 image-loader.tsloader 本体
templates/next.config.images.ts合并进你的 next.config.tsimages 配置段

.env.local 加一行(图片自定义域名,不带尾斜杠):

NEXT_PUBLIC_IMAGE_TRANSFORM_HOST=https://media.example.com

Step 3 — 验证

pnpm dev    # dev 模式 loader 直接回原图(不烧转换额度),先确认页面正常
pnpm build && pnpm start
# 打开页面,检查 <img> 的 src/srcset 是否形如:
# https://media.example.com/cdn-cgi/image/width=828,quality=75,format=auto/images/xxx.jpg
# curl -I 该 URL,响应头应有 cf-resized: internal=ok/...

浏览器支持 AVIF/WebP 时 format=auto 会自动出对应格式(看响应的 content-type)。

计费模型(把账算对地方)

Cloudflare TransformationsVercel(2025+ 新定价)
免费额度5,000 unique transformations/月Hobby 5,000 transformations/月(禁止商用
转换单价$0.50 / 1K(需 Images 付费计划)$0.05 / 1K(比 CF 便宜 10 倍)+ cache reads/writes
图片流量 egress$0Fast Data Transfer ≈ $0.15/GB
超额行为新转换报 9422,不静默扣费返回 402,不扣费

关键认知:Cloudflare 的转换单价其实比 Vercel 贵 10 倍,真正省钱的是 egress = 0。 媒体类站点成本大头是持续的字节分发而非一次性转换,所以总账 Cloudflare 赢;且 Vercel Hobby 禁商用,付费产品本来就要上 Pro。

计费单位是「源图 × 参数组合」(官方例子:2,000 张图 × 5 个尺寸 = 10,000 次计费转换),按自然月计。所以控制变体基数 = 控制账单:

  • URL 里只放 width + quality + format=auto(loader 模板已固定),不要把 height/fit/gravity 塞进去
  • next.config 收紧 deviceSizes/imageSizes 到真实需要的档位(模板给了推荐值)
  • quality 全站统一(默认 75),不要 90+——q=95 输出体积翻倍,视觉收益≈0

常见坑

  • /cdn-cgi/image/ 404:zone 没 Enable transformations(Step 1.2),或域名是 r2.dev
  • 9422 错误:免费额度(5,000/月)用完,当月新变体全挂。要么付费要么收紧 deviceSizes。
  • dev 环境烧额度:loader 模板在 NODE_ENV=development 直接回原图,别删这个分支。
  • 短参数w/h/q/f/g 是合法 alias;但 trim=1 不是合法语法(trim 要像素值组)。
  • remotePatterns 不生效:custom loader 完全绕过 /_next/imageimages.remotePatterns 白名单不再起约束作用;loader 模板改为「只转换自己媒体域名,第三方 URL 原样返回」来兜这个安全边界。
  • ⚠️ 安全:不要用 URL 转换做付费墙模糊图/cdn-cgi/image/blur=50/<源图> 的源图必须公开可访问,任何人删掉 /cdn-cgi/image/... 段就拿到原图。付费内容的模糊预览必须离线生成(见 [[nextjs-r2-paid-media]] skill 的做法)或用 Worker 内 Images binding。

什么时候不用本 skill

  • Next.js 部署在 Cloudflare Workers(OpenNext adapter):直接在 wrangler.jsoncimages.binding,获得完整兼容 /_next/image 的内置优化器,连 loader 都不用写。
  • 想要框架无关的图片组件:用 @unpic/react(支持 28 个 CDN,含 cloudflare / cloudflare_images 两个 provider)。
  • 图片存在第三方(非自有 zone)且不能迁移:URL 转换够不着,考虑 Cloudflare Images 产品(imagedelivery.net,含存储)或维持 Vercel 优化。

注意区分两个 Cloudflare 产品:本 skill 用的是 Image Transformations(zone 上的 /cdn-cgi/image,配 R2/自有存储,按转换计费);Cloudflare Imagesimagedelivery.net)是含存储和预定义变体的另一个产品,R2 场景下前者才是对的。

What ships with it: 2 files

3.0 KB alongside SKILL.md, 2 of them executable

templates/

Gives 0 of the 12 instructions most containers cloud skills give in ~2.0k tokens

Counted across 607 of the 657 authors here whose files we hold, read 2026-08-07

  • Run containers as a non-root userin 66 of 607, across 46 files
  • Use multi-stage buildsin 53 of 607, across 44 files
  • Use Promise.all for independent operationsin 47 of 607, across 13 files
  • Import directly instead of barrel filesin 46 of 607, across 12 files
  • Use ternary instead of AND for conditionalsin 45 of 607, across 12 files
  • Use Set or Map for O(1) lookupsin 42 of 607, across 10 files
  • Create a .dockerignore filein 41 of 607, across 31 files
  • Read individual rule files for detailsin 39 of 607, across 9 files
  • Copy dependency files before source codein 36 of 607, across 23 files
  • Authenticate server actions like API routesin 35 of 607, across 7 files
  • Use next/dynamic for heavy componentsin 34 of 607, across 9 files
  • Use React.cache for per-request deduplicationin 34 of 607, across 10 files

Said here and by no other author read

  • Use a custom next/image loader for Cloudflare transformations
  • Keep next/image lazy priority and srcset features intact
  • Copy the loader template to the project root
  • Merge image settings into next.config
  • Add the image host environment variable
  • Lock deviceSizes and imageSizes to necessary tiers

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.