Lazy loading với loading="lazy" cho images, React.lazy() + Suspense cho components, next/dynamic cho Next.js — không lazy load LCP image và đừng lazy load quá nhiều (waterfall).
- Lazy loading trì hoãn loading resources cho đến khi thực sự cần — giảm initial load time và Time to Interactive.
- Images: <img loading='lazy'> attribute là native browser lazy loading, browser load image khi cần thiết khi scroll đến; không dùng cho LCP image (dùng loading='eager' hoặc priority).
- Components trong React: const HeavyChart = React.lazy(() => import('./HeavyChart')) kết hợp <Suspense fallback={<Spinner/>}> — chunk được split tự động và load on demand; dùng cho large components, chart libraries, editors. next/dynamic trong Next.js: const DynamicMap = dynamic(() => import('./Map'), { loading: () => <p>Loading...</p>, ssr: false }) — thêm ssr: false để skip server-side rendering cho browser-only components.
- Route-based lazy loading: React Router <Suspense> + React.lazy() mỗi route là chunk riêng — standard approach.
- Preloading: sau lazy load, có thể preload chunk trước khi user navigate: import('./HeavyPage') trong onMouseEnter — reduce perceived latency.
- Intersection Observer API: detect khi element vào viewport để trigger lazy load — basis của nhiều lazy loading libraries.
- Trade-off: lazy loading adds waterfall (request phải chờ parent component render) — cẩn thận với critical path; chỉ lazy load truly non-critical components.