一键导入
image-delivery
Deliver responsive images via CDN with AVIF/WebP, placeholders, and progressive loading on iOS, Android, Flutter, and React Native.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Deliver responsive images via CDN with AVIF/WebP, placeholders, and progressive loading on iOS, Android, Flutter, and React Native.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Schedule, batch, and constrain background work with WorkManager, BGTaskScheduler, and push-over-poll patterns to minimize battery and data cost.
Attribute battery drain to CPU, radio, GPS, display, and background work using Android Battery Historian and Xcode Energy Log / Instruments Energy gauge.
Shrink APK/AAB and IPA size with R8/ProGuard, dead-code elimination, asset hygiene, and Android App Bundle / App Thinning best practices.
Cut local and CI build times on Android (Gradle config cache, build cache, KSP over KAPT) and iOS (Xcode build cache, ccache, modules). Use when clean builds exceed ten minutes.
Downsample, cache, and choose the right image format (AVIF, HEIC, WebP) to cut memory, network, and decode time on iOS and Android.
Find and fix common memory leaks caused by listeners, closures, singletons, and lifecycle mismatches on iOS, Android, Flutter, and React Native.
| name | image-delivery |
| description | Deliver responsive images via CDN with AVIF/WebP, placeholders, and progressive loading on iOS, Android, Flutter, and React Native. |
Image delivery has two sides: the pipeline that produces the right image at the right size for the right device, and the client that displays it without jank. This skill covers both.
Standard query API (examples: Cloudinary, imgix, Cloudflare Images, Fastly Image Optimizer):
/img/{id}?w=720&h=0&fit=cover&q=80&fm=auto
w / h — target pixels. h=0 preserves aspect.fit — cover | contain | crop.q — quality (75–85 for AVIF, 80–85 for WebP).fm=auto — CDN picks AVIF > WebP > JPEG based on Accept.Emit headers:
Cache-Control: public, max-age=31536000, immutable
Vary: Accept
Compute pixel size from the view, not the design canvas. Account for device scale.
iOS:
extension UIView {
func scaledPx(_ logical: CGFloat) -> Int { Int(logical * UIScreen.main.scale) }
func imageUrl(_ id: String) -> URL {
let w = scaledPx(bounds.width)
return URL(string: "https://cdn.example.com/img/\(id)?w=\(w)&fm=auto&q=80")!
}
}
Android:
fun ImageView.imageUrl(id: String): String {
val w = (width * resources.displayMetrics.density).toInt()
return "https://cdn.example.com/img/$id?w=$w&fm=auto&q=80"
}
Flutter:
String imageUrl(BuildContext c, String id, double logicalW) {
final w = (logicalW * MediaQuery.of(c).devicePixelRatio).round();
return 'https://cdn.example.com/img/$id?w=$w&fm=auto&q=80';
}
RN:
const px = (logical: number) => Math.round(logical * PixelRatio.get());
const url = (id: string, w: number) => `https://cdn.example.com/img/${id}?w=${px(w)}&fm=auto&q=80`;
Options, cheapest first:
color: "#c0b8a8" alongside the image URL.BlurHash in Kotlin (Coil):
imageView.load(url) {
placeholder(BlurHashDrawable(blurHashString, 32, 32))
crossfade(200)
}
SwiftUI + BlurHash:
AsyncImage(url: url) { phase in
switch phase {
case .success(let img): img.resizable().scaledToFill()
default: Color(uiColor: UIImage(blurHash: blurHashString, size: .init(width: 32, height: 32)) ?? .systemGray5.withAlphaComponent(1))
}
}
Ship two variants in parallel:
HTML progressive JPEGs still work over HTTP/2. AVIF has progressive tiles; WebP does not — fall back to two-tier.
RN example with Expo Image:
<Image
source={{ uri: fullUrl }}
placeholder={{ blurhash }}
transition={200}
contentFit="cover"
priority={isAboveFold ? 'high' : 'normal'}
/>
When the user is on a list and a detail screen is likely, prefetch the hero image.
Coil:
imageLoader.enqueue(ImageRequest.Builder(ctx).data(heroUrl).build())
SDWebImage:
SDWebImagePrefetcher.shared.prefetchURLs([heroURL])
Flutter:
precacheImage(CachedNetworkImageProvider(heroUrl), context);
Reserve space before the image arrives: set aspectRatio (or explicit width + height) on the container. Without it, content below shifts when the image swaps in, causing cumulative layout shift and input misfires.
SwiftUI:
AsyncImage(url: url).aspectRatio(16/9, contentMode: .fill)
Compose:
AsyncImage(url = url, modifier = Modifier.aspectRatio(16 / 9f))
Flutter:
AspectRatio(aspectRatio: 16 / 9, child: CachedNetworkImage(imageUrl: url))
Never decode the full video to get a poster; generate posters at upload time and deliver as regular images. If you must on-device, use AVAssetImageGenerator / MediaMetadataRetriever off the main thread and cache the result.
Track per-image:
p95 "first byte → visible pixel" should be under 500 ms on 4G for above-the-fold images.
fm=auto (AVIF/WebP/JPEG) with Vary: Accept.w/h.