圖片優化
規則
- 在 Next.js 中對所有圖片使用
next/image — 自動優化、懶加載、響應式 srcset
- 務必設定
width 和 height,或搭配 fill 並使用有尺寸的容器 — 防止版面位移 (CLS)
- 模糊佔位圖:在構建/上傳時使用
plaiceholder 生成 blurDataURL,或對靜態導入使用 placeholder="blur"
- 遠端圖片:在
next.config.js 中配置 remotePatterns — 白名單 CDN 域名
- 上傳流程:客戶端 → 預簽名 URL (S3/R2/Supabase Storage) → 直接上傳 → 將 URL 存入資料庫
- 上傳時調整大小:使用
sharp 在伺服器端創建多種尺寸(縮圖、中、完整)— 不要提供原始檔
- 格式:通過
next/image 自動格式提供 WebP/AVIF — 為相容性保留 JPEG 作為回退
- CDN 傳遞:將原始檔存儲在物件儲存 (S3, R2) 中,通過 CDN (CloudFront, Cloudflare) 提供,並攜帶快取標頭
- 最大檔案大小驗證:在客戶端(上傳前)和伺服器端(處理前)檢查 — 典型限制為 5-10MB
模式
import Image from "next/image";
<Image
src="/hero.jpg"
alt="英雄圖片"
width={1200}
height={630}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQ..."
priority // 首屏內容
/>
<div className="relative aspect-video">
<Image src={url} alt={alt} fill className="object-cover" sizes="(max-width: 768px) 100vw, 50vw" />
</div>
import sharp from "sharp";
async function processUpload(buffer: Buffer) {
const thumbnail = await sharp(buffer).resize(200, 200, { fit: "cover" }).webp({ quality: 80 }).toBuffer();
const medium = await sharp(buffer).resize(800).webp({ quality: 85 }).toBuffer();
const full = await sharp(buffer).resize(1920).webp({ quality: 90 }).toBuffer();
return { thumbnail, medium, full };
}
應避免
- 在 Next.js 中使用
<img> 標籤 — 會失去自動優化、懶加載和格式轉換
- 響應式圖片缺少
sizes prop — 瀏覽器無法選擇正確的 srcset 尺寸
- 提供未經調整大小的原始圖片 — 一個 5MB 的照片以 400px 顯示非常浪費
- 跳過檔案類型驗證 — 在伺服器端檢查 MIME 類型,而不只是副檔名