Mục lục

Ảnh nặng: Kẻ thù số 1 của Tốc độ

Chiến lược tối ưu hóa hình ảnh toàn diện: Từ định dạng thế hệ mới (AVIF/WebP) đến kỹ thuật ngăn chặn CLS và Lazy Loading thông minh.

Hình ảnh thường chiếm 50-70% dung lượng tải trang và là nguyên nhân hàng đầu gây điểm LCP (Largest Contentful Paint) thấp. Trong môi trường production, tối ưu hình ảnh không chỉ là dùng đúng thẻ tag, mà là xây dựng một quy trình phân phối ảnh (Image Delivery Pipeline).

1. Vấn đề của thẻ <img> truyền thống

Sử dụng thẻ <img> thuần túy trong các ứng dụng hiện đại gây ra các vấn đề nghiêm trọng về hiệu năng:

  1. Cumulative Layout Shift (CLS): Hình ảnh load chậm đẩy nội dung xuống dưới, gây giật lag giao diện.
  2. Over-fetching: Tải ảnh 4000px cho một khung hiển thị mobile 300px.
  3. Legacy Formats: Sử dụng JPEG/PNG thay vì các định dạng nén tốt hơn như WebP/AVIF.

2. Giải pháp: Next.js Image Component

Component next/image không chỉ là một wrapper UI, nó hoạt động như một hệ thống tối ưu hóa tự động.

Cơ chế hoạt động:

  1. On-demand Optimization: Ảnh gốc không được xử lý trước. Khi user request ảnh, Next.js Server (hoặc CDN) mới resize và nén ảnh cached cho lần sau.
  2. Format Negotiation: Tự động trả về AVIF cho Chrome, WebP cho Firefox, và JPEG cho Safari cũ dựa trên Accept header.
  3. Size Attributes: Bắt buộc khai báo width/height (hoặc fill) để trình duyệt dự trữ không gian, loại bỏ hoàn toàn CLS.
tsx:
import Image from 'next/image';
import heroImg from '/public/hero.jpg';

export function Hero() {
  return (
    <div className="relative h-[500px] w-full">
      <Image
        src={heroImg}
        alt="Hero Banner"
        fill
        priority
        sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
        className="object-cover"
      />
    </div>
  );
}

3. Chiến lược LCP (Largest Contentful Paint)

LCP là chỉ số đo tốc độ load của phần tử lớn nhất trong viewport. Để đạt điểm xanh (<2.5s), chiến lược tải ảnh cực kỳ quan trọng:

  1. Priority Loading: Luôn thêm property priority cho ảnh LCP (thường là ảnh Hero hoặc ảnh sản phẩm chính). Điều này thêm thẻ <link rel="preload"> vào HTML head.
  2. Avoid Lazy Loading LCP: Mặc định next/image dùng lazy loading. Điều này TỐT cho ảnh dưới fold, nhưng RẤT TỆ cho ảnh LCP. Luôn tắt lazy load cho ảnh đầu trang.
  3. Fetch Priority: Sử dụng fetchPriority="high" (Next.js 13.5+) để báo trình duyệt ưu tiên tải hình ảnh này trước cả CSS/JS không quan trọng.

4. Engineering Case Study: E-commerce Listing

Các trang thương mại điện tử lớn (như Amazon, Shopee) đối mặt với thách thức hiển thị hàng nghìn ảnh sản phẩm với tốc độ cuộn nhanh.

Giải pháp "Blur-up Placeholder": Thay vì để khoảng trắng trong khi ảnh đang load, họ sử dụng một phiên bản siêu nhỏ (10px) đã được base64 encode hoặc một chuỗi mã hóa màu (BlurHash).

Implementation trong Next.js: Sử dụng placeholder="blur" với ảnh import tĩnh, hoặc tự tạo BlurHash cho ảnh động từ API.

tsx:
// blurDataURL là chuỗi base64 pixel nhỏ của ảnh
<Image
  src={product.image}
  placeholder="blur"
  blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRg..." 
  {...props}
/>

5. Checklist Tối ưu hóa (Production Readiness)

  1. Format: Cấu hình next.config.js để ưu tiên formats: ['image/avif', 'image/webp']. AVIF nén tốt hơn WebP 20%.
  2. Sizes: Định nghĩa thuộc tính sizes chính xác. Đừng dùng 100vw cho mọi ảnh. Hãy media query chính xác (VD: Mobile 100vw, Tablet 50vw, Desktop 33vw).
  3. CDN: Sử dụng Edge Network (Vercel Blob, Cloudinary, Imgix) để serve ảnh từ server gần người dùng nhất.

Kết luận

Đừng phó mặc hình ảnh cho trình duyệt. Hãy kiểm soát kích thước, định dạng và thứ tự tải của từng bức ảnh để đảm bảo trải nghiệm người dùng nhanh nhất có thể.

Quảng cáo
mdhorizontal