Image optimization (Phần 2): Next.js Image Component
Giới thiệu
Ở phần trước mình đã nói về Image optimization và cách tối ưu image đối với HTML <img> tag
Khi sử dụng Next.js, nên dùng component Image (mở rộng từ HTML <img> tag) để tự động tối ưu hình ảnh.
Next.js Image component giúp tự động hóa phần lớn quá trình tối ưu image. Tuy nhiên, để đạt hiệu quả tốt nhất, vẫn cần hiểu rõ cách hoạt động của các props và config, cũng như cách browser xử lý image trong thực tế.
Nội dung
1. Một số props quan trọng:
import Image from 'next/image'
export default function Page() {
return (
<Image
src="/image.jpg"
alt="Example image"
width={500}
height={300}
sizes="(max-width: 768px) 100vw, 400px"
priority={false}
loading="lazy"
placeholder="blur"
blurDataURL="data:image/jpeg;base64,..."
quality={75}
/>
)
}
sizes
- Screen ≤ 768px: image rộng 100vw; > 768px: image rộng 400px
- Xác định kích thước hiển thị của image theo từng breakpoint
- Browser sẽ dựa vào
sizesđể chọn resource phù hợp từsrcset - Default là
100vw, nếu không cấu hình đúng, browser có thể tải image lớn hơn cần thiết
width / height
- Dùng để xác định aspect ratio, giúp browser chừa sẵn không gian và tránh layout shift (CLS)
- Kích thước hiển thị thực tế vẫn do CSS quyết định
// Hiển thị width: 400px
<Image
src="/image.jpg"
alt="Example image"
width={500}
height={300}
style={{ width: "400px", height: "auto" }}
sizes="400px"
/>
-
Nếu không xác định được width/height thì dùng
fill<div style={{ width: "100%", height: "300px", maxWidth: "800px", position: "relative" }} > <Image src="/image.jpg" alt="Example image" fill style={{ objectFit: "cover" }} sizes="(max-width: 768px) 100vw, 800px" /> </div>
priority
- Dùng cho hero / LCP image để preload và load sớm nhất
loading
- Default là
"lazy” - Chỉ dùng
"eager"khi không dùngprioritynhưng vẫn muốn load sớm
placeholder + blurDataURL
- Tạo hiệu ứng blur khi image đang load
- Giúp cải thiện perceived performance (cảm giác load nhanh hơn)
- Có thể sử dụng thư viện plaiceholder để generate blur data url
quality
- Giá trị từ 1–100 (default: 75) để điều chỉnh chất lượng ảnh.
- Giá trị càng cao thì ảnh rõ hơn nhưng dung lượng lớn hơn, càng thấp thì nhẹ hơn nhưng có thể giảm độ sắc nét.
2. Config trong next.config.js
Nếu không cấu hình, Next.js sẽ dùng mặc định:
images: {
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840]
imageSizes: [32, 48, 64, 96, 128, 256, 384],
formats: ['image/webp'],
qualities: 75
}
deviceSizes: danh sách breakpoint, tạo image lớn (responsive full-width)imageSizes:- Tạo image nhỏ (icon, card, avatar,…)
- Kết hợp với
deviceSizestạo thành danh sách kích thước đầy đủ ([32, 48,…, 384, 640, 750,…., 3840]) dùng để generatesrcset.
- Các giá trị trong
imageSizesphải nhỏ hơn giá trị nhỏ nhất củadeviceSizes.
Ngoài ra còn các config này chủ yếu ảnh hưởng đến caching, network và server load. Cấu hình hợp lý theo nhu cầu project giúp tăng cache hit, giảm latency và tránh xử lý lại image không cần thiết.
images: {
minimumCacheTTL: 14400, // 4 hours
disableStaticImages: false,
maximumRedirects: 3,
maximumDiskCacheSize: 500_000_000, //500 MB
maximumResponseBody: 50_000_000, //50 MB
}
Trong thực tế, nên giữ gần default và chỉ điều chỉnh khi gặp bottleneck cụ thể (cache miss cao, disk đầy, image quá lớn…)
3. Khi nào không cần optimize image?
Không cần quan tâm optimization đối với: các hình nhỏ (<1KB), SVG, hoặc GIF.
-
Sử dụng
unoptimizedprop<Image {...props} unoptimized /> -
Config trong
next.config.js(version từ 12.3.0)module.exports = { images: { unoptimized: true, }, }
4. Lưu ý các bugs có thể có trên browser (browser compatibility)
- Lazy loading: browser cũ (trước Safari 15.4) có thể fallback sang eager loading
- Placeholder: blur placeholder không hỗ trợ trước Safari 12 (fallback về empty)
- Aspect ratio: browser cũ (trước Safari 15) không giữ aspect ratio, có thể gây layout shift (CLS)
Lời kết
Cảm ơn bạn đã đọc bài viết. Nếu có góp ý, hãy để lại comment để mình có thể cập nhật và cải thiện nội dung.
All rights reserved