📰 مقالات 🎓 آموزش بارگذاری تنبل (Lazy Loading) …
📝 مقاله 🎓 آموزش

بارگذاری تنبل (Lazy Loading) — راهنمای کامل

چطور با معلق نگه داشتن تصاویر و ویدیوهای خارج از دید کاربر، سرعت اولیه‌ی صفحه را تا ۸۵٪ بالا ببریم

بارگذاری تنبل تصاویر — PyCourse
A
Amir hesam Vahdati
نویسنده
📅 ۱۴۰۵/۰۵/۲۴
8 دقیقه
👁 64
❤️ 4

در حالت عادی، مرورگر همه‌ی تصاویر، ویدیوها و اسکریپت‌های یک صفحه را به‌محض ورود کاربر دانلود می‌کند — حتی محتوایی که در انتهای صفحه است و شاید کاربر هیچ‌وقت به آن نرسد.

💡
ایده‌ی اصلی

هیچ منبعی را دانلود نکن مگر اینکه کاربر به آن نزدیک شده باشد. در این تکنیک، منابع خارج از دید کاربر (خارج از Viewport) تا لحظه‌ی اسکرول به حالت معلق باقی می‌مانند.

مقایسه‌ی عملکرد: قبل و بعد

برای درک تأثیر عملی، صفحه‌ای با ۵۰ تصویر محصول را در نظر بگیرید.

  • بدون Lazy Load: مرورگر هر ۵۰ تصویر (حدود ۵۰ مگابایت) را یک‌جا دانلود می‌کند؛ بارگذاری اولیه بیش از ۱۵ ثانیه طول می‌کشد و ترافیک کاربر هدر می‌رود.
  • با Lazy Load: فقط ۴ تصویر ابتدای صفحه (حدود ۴ مگابایت) دانلود می‌شود؛ زمان لود اولیه به زیر ۳ ثانیه می‌رسد.
⚠️
دقت کن

این اعداد برای یک صفحه‌ی پرتصویر با تصاویر بهینه‌نشده است. میزان بهبود به تعداد تصاویر، حجمشان و سرعت اینترنت کاربر بستگی دارد — پس قبل و بعد را روی سایت خودت اندازه بگیر، نه اینکه فرض کنی.

روش ۱: پیاده‌سازی بومی در HTML

ساده‌ترین راه و بدون یک خط جاوااسکریپت: کافی است صفت loading="lazy" را به تگ‌های img یا iframe اضافه کنی. همه‌ی مرورگرهای مدرن پشتیبانی می‌کنند.

🌐 HTML — تصاویر و فریم‌های پایین صفحه
<!-- تصاویر پایین صفحه --> <img src="product.jpg" loading="lazy" alt="نام محصول" width="800" height="600" /> <!-- ویدیوها و فریم‌های یوتیوب --> <iframe src="https://www.youtube.com/embed/example" loading="lazy" width="560" height="315"> </iframe>
🔴
نکته‌ی الزامی

تعیین width و height اجباری است. بدون آن‌ها مرورگر جای تصویر را از قبل نمی‌داند و هنگام لود، محتوا ناگهان می‌پرد. این همان مشکل CLS است که گوگل برایش جریمه‌ی سئو در نظر می‌گیرد.

روش ۲: کنترل دقیق با IntersectionObserver

اگر می‌خواهی زمان بارگذاری را خودت کنترل کنی — مثلاً تصویر ۲۰۰ پیکسل قبل از رسیدن اسکرول کاربر لود شود تا هیچ‌وقت جای خالی نبیند — از این API بومی جاوااسکریپت استفاده کن.

🌐 HTML — HTML — آدرس واقعی در data-src
<img data-src="real-image.jpg" src="placeholder.jpg" alt="توضیح تصویر" width="400" height="300" class="lazy-img" />
✨ JAVASCRIPT — JavaScript
const lazyImages = document.querySelectorAll('img.lazy-img'); const imageObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src; img.removeAttribute('data-src'); observer.unobserve(img); // دیگر لازم نیست رصدش کنیم } }); }, { rootMargin: "0px 0px 200px 0px" // ۲۰۰ پیکسل زودتر شروع کن }); lazyImages.forEach(img => imageObserver.observe(img));
💡
چرا unobserve؟

بعد از لود شدن تصویر، دیگر دلیلی برای رصد کردنش نیست. بدون این خط، observer تا آخر عمر صفحه همه‌ی تصاویر را زیر نظر می‌گیرد و بی‌جهت منابع مصرف می‌کند.

روش ۳: بارگذاری تنبل کامپوننت‌ها در React

در پروژه‌های جاوااسکریپتی، کامپوننت‌های سنگین یا مودال‌هایی که شاید هیچ‌وقت باز نشوند را فقط هنگام نیاز بارگذاری کن تا حجم فایل اصلی (Bundle Size) کم شود.

✨ JAVASCRIPT — React.lazy و Suspense
import React, { Suspense, lazy } from 'react'; const HeavyChart = lazy(() => import('./HeavyChart')); function Dashboard() { return ( <div> <Suspense fallback={<div>در حال بارگذاری بخش آمار...</div>}> <HeavyChart /> </Suspense> </div> ); }

روش ۴: اسکرول بی‌نهایت

همان منطق را می‌شود روی داده هم اعمال کرد: وقتی کاربر به انتهای صفحه نزدیک شد، صفحه‌ی بعدی داده را بگیر.

✨ JAVASCRIPT — تشخیص رسیدن به انتهای صفحه
window.addEventListener('scroll', () => { if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 200) { loadNextPageData(); } });
⚠️
یک بهبود مهم

رویداد scroll ده‌ها بار در ثانیه اجرا می‌شود. در پروژه‌ی واقعی حتماً آن را با debounce یا throttle کنترل کن، یا بهتر از آن، همان IntersectionObserver را روی یک عنصر نگهبان در انتهای فهرست بگذار — هم دقیق‌تر است هم سبک‌تر.

تجربه‌ی کاربری: جای خالی را پر کن

تا وقتی تصویر لود نشده، کاربر نباید کادر سفید خالی ببیند. یک انیمیشن ساده‌ی نبض، حس «در حال بارگذاری» می‌دهد و انتظار را کوتاه‌تر نشان می‌دهد.

🎨 CSS — انیمیشن بارگذاری
.lazy-img { background-color: #f0f0f0; animation: pulse 1.5s infinite ease-in-out; } @keyframes pulse { 0%, 100% { opacity: 0.6; } 50% { opacity: 1; } }

خط قرمزها: کجا نباید استفاده کرد؟

  • ❌ تصویر اصلی بالای صفحه (Hero Image) — این تصویر شاخص LCP در سئوست و تنبل کردنش مستقیماً سرعت اولیه‌ی سایت را پایین می‌آورد.
  • ❌ صفحات متنی خیلی ساده — پیچیدگی کد بدون تغییر ملموس در عملکرد.
  • ✅ تصاویر گالری و محصولات پایین صفحه — صرفه‌جویی شدید در ترافیک.
  • ✅ ویدیوها، iframeها و نقشه‌ها — جلوگیری از اجرای اسکریپت‌های سنگین جانبی در لحظه‌ی ورود.
🔴
مهم‌ترین اشتباه رایج

loading="lazy" گذاشتن روی تصویر اصلی بالای صفحه. خیلی‌ها آن را روی همه‌ی تصاویر سایت اعمال می‌کنند و بعد تعجب می‌کنند که چرا نمره‌ی سرعتشان بدتر شد. تصویری که کاربر بدون اسکرول می‌بیند، باید هرچه سریع‌تر لود شود.

جمع‌بندی

بارگذاری تنبل یکی از کم‌هزینه‌ترین بهینه‌سازی‌هاست: برای اکثر سایت‌ها فقط یک صفت HTML لازم است. قاعده‌ی ساده این است — هرچه کاربر بدون اسکرول می‌بیند را فوری لود کن، بقیه را تا لحظه‌ی نیاز معلق نگه دار. و بعد از هر تغییر، با Lighthouse یا تب Network اندازه بگیر تا مطمئن شوی واقعاً بهتر شده.