آموزش تکنیک های Asynchronous Loading | افزایش سرعت سایت

استفاده از تکنیک های Asynchronous Loading
زمانی که یک وب سایت در حال بارگذاری است، سرعت از اهمیت حیاتی برخوردار می شود. بارگذاری ناهمزمان (Asynchronous Loading) روشی برای بهبود این تجربه است، به این صورت که اجزای صفحه مانند اسکریپت ها، استایل ها، تصاویر و فونت ها بدون بلوکه کردن رندر اولیه صفحه، به صورت موازی یا در زمان مناسب تری بارگذاری می شوند. این رویکرد به مرورگر امکان می دهد محتوای اصلی را سریع تر نمایش دهد و تعامل کاربر با صفحه را بهبود بخشد.
مسیر هر وب سایت به سمت موفقیت، با سرعت آن گره خورده است. سرعت بارگذاری یک وب سایت نه تنها بر تجربه کاربری تأثیر مستقیم می گذارد، بلکه نقش کلیدی در موفقیت کسب وکارها، نرخ تبدیل و حتی جایگاه آن در نتایج موتورهای جستجو ایفا می کند. یک وب سایت کند، کاربران را دلزده می کند و منجر به ترک صفحه پیش از مشاهده محتوای کامل می شود. در مقابل، وب سایتی که با سرعت خیره کننده ای بارگذاری می شود، کاربران را جذب کرده و تجربه ای لذت بخش برایشان رقم می زند. تصور کنید کاربری به دنبال اطلاعاتی است؛ او با وب سایتی سریع مواجه می شود که بلافاصله محتوا را در اختیارش قرار می دهد، در حالی که وب سایت رقیب هنوز در حال بارگذاری است. واضح است که کدام یک برنده این رقابت خواهد بود.
چرا سرعت مهم است؟
دنیای وب همیشه در حال حرکت به سمت سرعت و کارایی بیشتر بوده است. زمانی که یک وب سایت دیر بارگذاری می شود، این تأخیر می تواند هزینه های پنهان زیادی داشته باشد، از دست دادن کاربران بالقوه تا کاهش رتبه در موتورهای جستجو. درک این موضوع به هر توسعه دهنده و صاحب وب سایتی کمک می کند تا اهمیت بهینه سازی بارگذاری را بیش از پیش دریابد.
اهمیت سرعت بارگذاری وب سایت
تجربه یک کاربر از وب سایت شما، اولین چیزی است که در ذهن او نقش می بندد. اگر صفحه شما در چند ثانیه اول ظاهر نشود، احتمال بالایی وجود دارد که کاربر آن را ترک کند. مطالعات متعددی نشان داده اند که با هر ثانیه تأخیر در بارگذاری، نرخ خروج (Bounce Rate) افزایش یافته و نرخ تبدیل (Conversion Rate) کاهش می یابد. در واقع، سرعت نه تنها یک ویژگی فنی، بلکه یک سرمایه گذاری حیاتی در کسب وکار آنلاین محسوب می شود. زمانی که کاربران با وب سایتی مواجه می شوند که بدون معطلی پاسخگو است، حس رضایت و اعتماد در آن ها تقویت می شود.
معرفی Core Web Vitals و ارتباط آن با بارگذاری
گوگل با معرفی معیارهای Core Web Vitals، اهمیت سرعت و تجربه کاربری را بیش از پیش برجسته کرد. این معیارها شامل سه شاخص اصلی هستند که مستقیماً به عملکرد بارگذاری وب سایت مربوط می شوند:
- Largest Contentful Paint (LCP): زمان لازم برای بارگذاری بزرگ ترین عنصر محتوایی قابل مشاهده در صفحه. بهبود این زمان مستلزم بارگذاری بهینه تمامی دارایی ها، به ویژه تصاویر و فونت ها است.
- First Input Delay (FID): زمان بین اولین تعامل کاربر با صفحه (مثلاً کلیک روی یک دکمه) و پاسخ مرورگر به آن تعامل. جاوااسکریپت بلوکه کننده رندر و اجرای سنگین می تواند FID را به شدت تحت تأثیر قرار دهد.
- Cumulative Layout Shift (CLS): میزان تغییرات ناگهانی و غیرمنتظره در چیدمان بصری صفحه. بارگذاری ناهمزمان و هوشمندانه فونت ها و تصاویر می تواند از CLS جلوگیری کند.
این معیارها نه تنها بر تجربه کاربری تأثیر می گذارند، بلکه به یکی از فاکتورهای رتبه بندی گوگل نیز تبدیل شده اند. این یعنی بهبود آن ها مستقیماً به بهتر دیده شدن وب سایت شما در نتایج جستجو کمک می کند.
چرا بارگذاری سنکرون (Synchronous) مشکل ساز است؟
در بارگذاری سنکرون، مرورگر به ترتیب کدهای HTML، CSS و JavaScript را پردازش می کند. وقتی به یک اسکریپت یا فایل CSS می رسد که به صورت سنکرون بارگذاری شده، باید منتظر بماند تا آن فایل به طور کامل دانلود و اجرا شود، پیش از اینکه به پردازش بقیه صفحه ادامه دهد. این مکث، باعث بلوکه شدن رندر (Render Blocking) می شود.
بارگذاری سنکرون مانند صفی طولانی است؛ هر فرد باید منتظر بماند تا نفر قبلی کارش را تمام کند، حتی اگر کار او به نفرات بعدی وابسته نباشد.
این بلوکه شدن می تواند تجربه کاربری را به شدت تحت تأثیر قرار دهد و باعث شود صفحه برای مدت طولانی تری سفید یا غیرقابل استفاده به نظر برسد. در دنیایی که کاربران به سرعت عادت کرده اند، حتی چند صد میلی ثانیه تأخیر می تواند به معنای از دست دادن مخاطب باشد.
بارگذاری ناهمزمان چیست؟ (توضیح عمیق تر)
بارگذاری ناهمزمان، پاسخی به چالش های بارگذاری سنکرون است. این مفهوم به مرورگر اجازه می دهد تا چندین کار را به طور همزمان یا به ترتیبی که منجر به بهترین تجربه کاربری شود، انجام دهد. به عبارت دیگر، مرورگر مجبور نیست برای بارگذاری هر دارایی (Asset) منتظر بماند تا فرآیند بارگذاری کل صفحه متوقف شود.
مقایسه بارگذاری سنکرون و ناهمزمان
برای درک بهتر تفاوت، یک سناریو را تصور کنید:
- سنکرون: مرورگر ابتدا HTML را می خواند. اگر به یک اسکریپت برسد، مکث می کند، اسکریپت را دانلود می کند، اجرا می کند و سپس به ادامه خواندن HTML می پردازد. اگر اسکریپت بزرگ باشد یا از سرور دور، این توقف می تواند بسیار طولانی باشد.
- ناهمزمان: مرورگر به خواندن HTML ادامه می دهد و در همان حین، اسکریپت ها یا سایر دارایی ها را در پس زمینه دانلود می کند. به محض اینکه یک اسکریپت ناهمزمان آماده اجرا شد، اجرا می شود، بدون اینکه لزوماً منتظر تمام شدن بارگذاری HTML باشد. این فرآیند باعث می شود کاربر سریع تر محتوای بصری صفحه را مشاهده کند.
مفهوم مرورگر و Event Loop
در قلب عملکرد ناهمزمان مرورگرها، مفهومی به نام Event Loop قرار دارد. مرورگرها تک رشته ای (Single-threaded) هستند، به این معنی که نمی توانند چندین عملیات جاوااسکریپت را به طور همزمان در رشته اصلی (main thread) اجرا کنند. اما این بدان معنا نیست که نمی توانند کارهای ناهمزمان انجام دهند. Event Loop سیستمی است که به جاوااسکریپت اجازه می دهد تا عملیات های زمان بر (مانند درخواست های شبکه یا تایمرها) را به پس زمینه بسپارد و پس از اتمام آن ها، نتایج را به رشته اصلی بازگرداند.
وقتی یک عملیات ناهمزمان آغاز می شود، مرورگر آن را به APIهای مرورگر (Web APIs) می سپارد. Web APIs وظیفه مدیریت عملیات هایی مانند Fetch (برای درخواست های شبکه)، DOM events یا setTimeout را بر عهده دارند. پس از اتمام کار در Web API، نتیجه به صف پیام ها (Message Queue) فرستاده می شود. Event Loop به طور مداوم این صف را بررسی می کند و هر زمان که رشته اصلی آزاد باشد، وظایف موجود در صف پیام ها را به رشته اصلی منتقل کرده و اجرا می کند. این چرخه تضمین می کند که رابط کاربری (UI) وب سایت پاسخگو باقی بماند، حتی زمانی که کارهای سنگین در پس زمینه در حال انجام هستند.
تکنیک های Asynchronous Loading برای JavaScript
جاوااسکریپت اغلب یکی از بزرگ ترین و تأثیرگذارترین دارایی ها بر سرعت بارگذاری صفحه است. مدیریت صحیح بارگذاری اسکریپت ها می تواند تفاوت چشمگیری در عملکرد وب سایت ایجاد کند.
الف) ویژگی های async
و defer
در تگ <script>
تگ <script>
دو ویژگی قدرتمند به نام های async
و defer
دارد که به توسعه دهندگان کنترل بیشتری بر نحوه بارگذاری و اجرای جاوااسکریپت می دهد.
شرح کامل async
ویژگی async
به مرورگر دستور می دهد که اسکریپت را به صورت ناهمزمان دانلود کند. این به معنای آن است که مرورگر می تواند در حالی که مشغول دانلود اسکریپت است، به تجزیه و تحلیل (parsing) HTML صفحه ادامه دهد.
- عملکرد: اسکریپت با ویژگی
async
غیر بلوکه کننده است. دانلود آن موازی با تجزیه HTML انجام می شود. به محض اینکه دانلود کامل شد، تجزیه HTML موقتاً متوقف می شود و اسکریپت بلافاصله اجرا می شود. پس از اجرای اسکریپت، تجزیه HTML از سر گرفته می شود. - ترتیب اجرا: ترتیب اجرای اسکریپت هایی که دارای
async
هستند، نامشخص است. هر اسکریپت به محض اتمام دانلود و آماده شدن، اجرا می شود. بنابراین، اگر چندین اسکریپتasync
داشته باشید، نمی توانید تضمین کنید که کدام یک زودتر اجرا خواهد شد. - موارد استفاده: این ویژگی برای اسکریپت هایی ایده آل است که مستقل از DOM (Document Object Model) و سایر اسکریپت ها عمل می کنند. مثال های رایج شامل اسکریپت های آنالیتیکس (مانند گوگل آنالیتیکس)، تبلیغات یا ابزارهای پایش عملکرد است که نیازی به تغییر فوری ساختار صفحه ندارند.
<script src=analytics.js async></script>
<script src=ads.js async></script>
در مثال بالا، analytics.js
و ads.js
به طور موازی دانلود شده و به محض آماده شدن اجرا می شوند، بدون اینکه منتظر یکدیگر یا پایان تجزیه HTML باشند.
شرح کامل defer
ویژگی defer
نیز به مرورگر اجازه می دهد اسکریپت را به صورت ناهمزمان دانلود کند، اما نحوه اجرای آن متفاوت است.
- عملکرد: اسکریپت با ویژگی
defer
نیز غیر بلوکه کننده است و دانلود آن موازی با تجزیه HTML انجام می شود. اما برخلافasync
، اجرای اسکریپت تا زمانی که تمام HTML صفحه تجزیه و تحلیل نشده و DOM آماده نشده است، به تعویق می افتد. این یعنی اسکریپت پس از کامل شدن DOMContentLoaded Event اجرا می شود. - ترتیب اجرا: اسکریپت هایی که دارای
defer
هستند، به همان ترتیبی که در کد HTML قرار گرفته اند، اجرا می شوند. این ویژگی برای سناریوهایی که اسکریپت ها به یکدیگر یا به ساختار DOM وابسته هستند، بسیار مهم است. - موارد استفاده:
defer
برای جاوااسکریپت هایی که به DOM دسترسی دارند و باید پس از بارگذاری کامل صفحه اجرا شوند، مناسب است. مثال های رایج شامل اسکریپت هایی که عناصر UI را دستکاری می کنند، کتابخانه هایی مانند jQuery، یا اسکریپت های فرم ها هستند.
<script src=jquery.js defer></script>
<script src=main-app.js defer></script>
در این مثال، jquery.js
قبل از main-app.js
اجرا می شود و هر دو پس از آماده شدن DOM اجرا خواهند شد.
مقایسه جامع async
و defer
انتخاب بین async
و defer
به وابستگی ها و ترتیب اجرای اسکریپت های شما بستگی دارد. درک تفاوت های کلیدی آن ها می تواند به تصمیم گیری صحیح کمک کند:
ویژگی | async |
defer |
---|---|---|
نحوه دانلود | موازی با تجزیه HTML | موازی با تجزیه HTML |
نحوه اجرا | به محض دانلود کامل (بلوکه کردن تجزیه HTML در زمان اجرا) | پس از تجزیه کامل HTML و قبل از رویداد DOMContentLoaded (بدون بلوکه کردن) |
ترتیب اجرا | نامشخص | حفظ ترتیب در سند HTML |
وابستگی به DOM | عدم نیاز یا وابستگی کم | نیاز به دسترسی به DOM |
مثال های کاربرد | آنالیتیکس، تبلیغات، اسکریپت های مستقل | کتابخانه ها (jQuery)، اسکریپت های دستکاری DOM، تعاملات UI |
به طور خلاصه، اگر اسکریپتی به هیچ چیز دیگری وابسته نیست و هیچ چیز دیگری به آن وابسته نیست، async
انتخاب خوبی است. اگر اسکریپت به DOM یا اسکریپت های دیگر وابسته است و ترتیب اجرای آن اهمیت دارد، defer
را انتخاب کنید.
ب) Dynamic Imports (وارد کردن پویا)
وارد کردن پویا، تکنیکی مدرن در جاوااسکریپت است که به توسعه دهندگان امکان می دهد ماژول ها را تنها در زمانی که واقعاً به آن ها نیاز است، بارگذاری کنند. این روش، به ویژه برای برنامه های تک صفحه ای (SPA) و وب سایت های بزرگ با قابلیت های متنوع، بسیار مفید است.
- چیستی و کاربرد: Dynamic Imports به شما اجازه می دهد کد را به بخش های کوچک تر تقسیم کنید (Code Splitting). به جای بارگذاری تمامی جاوااسکریپت های وب سایت در ابتدای کار، می توانید بخش های خاصی از کد را تنها زمانی که کاربر به آن ویژگی خاص نیاز دارد (مثلاً با کلیک روی یک دکمه یا اسکرول به یک بخش خاص) بارگذاری کنید.
- نحوه پیاده سازی: این کار با استفاده از تابع
import()
که یک Promise برمی گرداند، انجام می شود.
// بارگذاری یک ماژول فقط زمانی که کاربر روی دکمه کلیک می کند
document.getElementById('myButton').addEventListener('click', () => {
import('./myModule.js')
.then(module => {
module.doSomething();
})
.catch(err => {
console.error('Failed to load module', err);
});
});
- مزایا:
- کاهش حجم اولیه بارگذاری: کاربر تنها کدی را دریافت می کند که برای نمایش اولیه صفحه ضروری است، که به بهبود LCP کمک می کند.
- بارگذاری شرطی: ماژول ها می توانند بر اساس منطق برنامه (مثلاً نقش کاربر، اندازه صفحه) بارگذاری شوند.
- بهبود FID: با کاهش حجم کد جاوااسکریپت در بارگذاری اولیه، رشته اصلی سریع تر آزاد می شود.
ج) Web Workers
همانطور که قبلاً اشاره شد، جاوااسکریپت در مرورگر تک رشته ای است. این بدان معناست که عملیات های سنگین جاوااسکریپت می توانند رشته اصلی مرورگر را برای مدتی طولانی بلوکه کنند و باعث شوند رابط کاربری غیرپاسخگو شود. Web Workers برای حل این مشکل طراحی شده اند.
- مفهوم و کاربرد: Web Workers به شما اجازه می دهند اسکریپت های جاوااسکریپت را در یک رشته پس زمینه (Background Thread) جداگانه اجرا کنید. این بدان معناست که کارهای سنگین محاسباتی یا عملیات های پیچیده می توانند بدون تأثیر بر پاسخگویی رابط کاربری اصلی، انجام شوند.
- نحوه پیاده سازی: برای ایجاد یک Web Worker، یک فایل جاوااسکریپت جداگانه تعریف می کنید که کد مورد نظر شما در آن قرار دارد.
// main.js (در رشته اصلی)
if (window.Worker) {
const myWorker = new Worker('worker.js');
myWorker.postMessage('Start calculation'); // ارسال پیام به Worker
myWorker.onmessage = function(e) { // دریافت پیام از Worker
console.log('Result from worker:', e.data);
};
myWorker.onerror = function(e) {
console.error('Worker error:', e);
};
}
// worker.js (فایل Worker)
onmessage = function(e) {
console.log('Message received from main script:', e.data);
let result = 0;
for (let i = 0; i < 1000000000; i++) {
result += i; // انجام یک عملیات سنگین
}
postMessage(result); // ارسال نتیجه به رشته اصلی
};
- محدودیت ها: Web Workers به DOM دسترسی ندارند، بنابراین نمی توانند عناصر HTML را به طور مستقیم دستکاری کنند. ارتباط بین Web Worker و رشته اصلی تنها از طریق ارسال و دریافت پیام انجام می شود. همچنین، آن ها نمی توانند مستقیماً به بسیاری از APIهای مرورگر مانند
localStorage
یاXMLHttpRequest
دسترسی داشته باشند (مگر از طریق پیام رسانی به رشته اصلی).
تکنیک های Asynchronous Loading برای CSS
CSS نیز می تواند به یکی از عوامل بلوکه کننده رندر تبدیل شود، به ویژه اگر فایل های استایل شیت بزرگ باشند. بهینه سازی بارگذاری CSS برای First Contentful Paint (FCP) و LCP بسیار مهم است.
الف) Critical CSS (CSS حیاتی)
Critical CSS به آن بخش از کدهای CSS گفته می شود که برای رندر کردن محتوای بالای خط دید (Above-the-fold) صفحه ضروری است. یعنی آن بخش از صفحه که بدون اسکرول کردن قابل مشاهده است.
- مفهوم و اهمیت: با اینلاین کردن (Inline) Critical CSS مستقیماً در تگ
<style>
داخل<head>
سند HTML، مرورگر می تواند بلافاصله پس از دریافت HTML، استایل های اولیه را اعمال کند. این کار از Flash of Unstyled Content (FOUC) جلوگیری می کند و LCP را به شکل چشمگیری بهبود می بخشد. CSS باقی مانده (غیرحیاتی) می تواند به صورت ناهمزمان بارگذاری شود. - نحوه استخراج و Inline کردن CSS حیاتی: استخراج Critical CSS معمولاً به صورت خودکار با ابزارهایی مانند Critters، Critical، یا پلاگین های Webpack انجام می شود. این ابزارها صفحه را تحلیل کرده و CSS لازم برای رندر اولیه را شناسایی می کنند.
- روش های بارگذاری CSS غیرحیاتی: پس از استخراج CSS حیاتی، فایل CSS اصلی را می توان به روش های مختلفی بارگذاری کرد تا بلوکه کننده نباشد:
- استفاده از
media=print
و تغییر با جاوااسکریپت: این یک ترفند قدیمی اما موثر است. مرورگر فایل CSS را با اولویت پایین تر دانلود می کند زیرا تصور می کند برای پرینت استفاده می شود، سپس با جاوااسکریپتmedia
آن را بهall
تغییر می دهیم.
<link rel=stylesheet href=/path/to/my.css media=print onload=this.media='all'> <noscript><link rel=stylesheet href=/path/to/my.css></noscript>
- استفاده از
- استفاده از JavaScript: می توانید فایل CSS را با جاوااسکریپت و پس از بارگذاری صفحه به DOM اضافه کنید.
<script>
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = '/path/to/my.css';
document.head.appendChild(link);
</script>
ب) Preloading (بارگذاری اولیه) CSS با <link rel=preload>
<link rel=preload>
به مرورگر می گوید که یک منبع خاص (مانند CSS، فونت، یا تصویر) را در اسرع وقت دانلود کند، زیرا این منبع در آینده نزدیک مورد نیاز خواهد بود. این ویژگی برای منابعی که در اوایل فرآیند رندر مورد نیازند اما مرورگر ممکن است به سرعت آن ها را کشف نکند، بسیار مفید است.
- استفاده از
<link rel=preload>
(برای CSS بسیار مهم): شما می توانید یک فایل CSS را preload کنید و سپس آن را با ویژگیonload
به صفحه اضافه کنید تا از بلوکه شدن رندر جلوگیری شود.
<link rel=preload href=styles.css as=style onload=this.rel='stylesheet'>
preload
برای مرورگرهای مدرن پشتیبانی خوبی دارد. مهم است که از as=style
برای CSS استفاده شود تا مرورگر آن را به عنوان یک استایل شیت تشخیص دهد. همچنین، پس از بارگذاری، باید rel=stylesheet
را اعمال کنید.با استراتژی Critical CSS و Preload، می توانید مطمئن شوید که تجربه بصری اولیه کاربر بدون تأخیر و کاملاً استایل بندی شده خواهد بود.
تکنیک های Asynchronous Loading برای تصاویر و ویدئوها (Lazy Loading)
تصاویر و ویدئوها می توانند حجم قابل توجهی از داده های یک صفحه را تشکیل دهند و به طور مستقیم بر سرعت بارگذاری اولیه و Core Web Vitals تأثیر بگذارند. Lazy Loading یک راهکار قدرتمند برای حل این مشکل است.
الف) Lazy Loading بومی مرورگر (loading=lazy
)
مرورگرهای مدرن یک ویژگی بومی برای Lazy Loading تصاویر و iframe ها ارائه می دهند که فرآیند را بسیار ساده می کند.
- شرح و کاربرد: با افزودن ویژگی
loading=lazy
به تگ<img>
یا<iframe>
، مرورگر تنها زمانی آن منبع را بارگذاری می کند که نزدیک به Viewport کاربر (یعنی در آستانه دیده شدن) قرار گیرد. - سازگاری مرورگرها: این ویژگی در کروم، فایرفاکس، اج و سافاری (نسخه های جدیدتر) پشتیبانی می شود.
- مثال کد:
<img src=image.jpg alt=Description loading=lazy>
<iframe src=video.mp4 loading=lazy></iframe>
این ساده ترین و توصیه شده ترین روش برای Lazy Loading است، چرا که مرورگر می تواند بهترین تصمیم را بر اساس اتصال کاربر و سایر عوامل بگیرد.
ب) Lazy Loading با JavaScript و Intersection Observer API
با وجود پشتیبانی بومی، ممکن است برای کنترل دقیق تر، پشتیبانی از مرورگرهای قدیمی تر، یا برای عناصری غیر از <img>
و <iframe>
، همچنان به راه حل های جاوااسکریپتی نیاز باشد. Intersection Observer API ابزاری مدرن و کارآمد برای این منظور است.
- چرا هنوز نیاز است؟ برای سناریوهای خاصی که نیاز به منطق بارگذاری سفارشی دارید (مثلاً بارگذاری تصاویر پس زمینه CSS، یا کنترل دقیق تر بر آستانه بارگذاری).
- نحوه پیاده سازی: Intersection Observer به شما امکان می دهد تا زمانی که یک عنصر وارد یا از Viewport خارج می شود، رویدادی را تشخیص دهید.
<img data-src=image.jpg alt=Description class=lazyload>
<script>
document.addEventListener(DOMContentLoaded, function() {
var lazyImages = [].slice.call(document.querySelectorAll(img.lazyload));
if (IntersectionObserver in window) {
let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
let lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
lazyImage.classList.remove(lazyload);
lazyImageObserver.unobserve(lazyImage);
}
});
});
lazyImages.forEach(function(lazyImage) {
lazyImageObserver.observe(lazyImage);
});
} else {
// Fallback for older browsers (e.g., using scroll/resize events, less performant)
console.log(IntersectionObserver not supported, implement fallback.);
lazyImages.forEach(function(img) {
img.src = img.dataset.src;
});
}
});
</script>
- مزایا: کنترل دقیق تر، عملکرد بهتر نسبت به رویدادهای اسکرول سنتی، قابلیت استفاده برای هر عنصر.
- معایب: نیاز به جاوااسکریپت و کدنویسی بیشتر.
ج) Placeholders و Low-Quality Image Placeholders (LQIP)
حتی با Lazy Loading، ممکن است در لحظه بارگذاری تصویر، یک فضای خالی ظاهر شود که می تواند باعث CLS شود. برای بهبود تجربه، می توان از Placeholder (جای نما) استفاده کرد.
- Placeholders: فضایی که برای تصویر رزرو می شود تا در زمان بارگذاری، چیدمان صفحه جابجا نشود. این کار با تنظیم ابعاد (width و height) تصویر در HTML یا CSS انجام می شود.
- LQIP (Low-Quality Image Placeholders): بارگذاری یک نسخه بسیار کوچک و با کیفیت پایین از تصویر اصلی (مانند یک تصویر بندانگشتی بلوری شده) به عنوان Placeholder. این کار حس بهتری به کاربر می دهد، زیرا چیزی را مشاهده می کند، حتی اگر کیفیت پایین باشد، تا زمانی که تصویر اصلی بارگذاری شود.
- برای پیاده سازی LQIP، می توانید از تصاویر کوچک با فرمت WebP یا JPEG با فشرده سازی بالا استفاده کنید. سپس، پس از بارگذاری کامل تصویر اصلی، آن را با کیفیت بالا جایگزین کنید.
تکنیک های Asynchronous Loading برای فونت ها
فونت های وب (Web Fonts) می توانند زیبایی بصری خاصی به وب سایت ببخشند، اما اگر به درستی مدیریت نشوند، می توانند باعث تأخیر در رندر متن و پدیده هایی مانند FOIT (Flash of Invisible Text) یا FOUT (Flash of Unstyled Text) شوند و بر CLS تأثیر بگذارند.
الف) استفاده از font-display
ویژگی CSS font-display
در قانون @font-face
به مرورگر می گوید که چگونه یک فونت را زمانی که هنوز بارگذاری نشده، نمایش دهد یا پنهان کند.
- مفهوم و مقادیر:
swap
: این مقدار محبوب ترین گزینه است. متن در ابتدا با یک فونت سیستمی جایگزین (fallback font) نمایش داده می شود. به محض اینکه فونت وب بارگذاری شد، متن با فونت اصلی سواپ می شود. این باعث FOIT نمی شود، اما ممکن است CLS خفیفی ایجاد کند.block
: مرورگر برای مدت کوتاهی متن را پنهان می کند (معمولاً تا 3 ثانیه) و منتظر می ماند تا فونت وب بارگذاری شود. اگر فونت در این مدت بارگذاری نشود، با یک فونت جایگزین نمایش داده می شود. این می تواند منجر به FOIT شود.fallback
: مشابهblock
، اما دوره پنهان سازی بسیار کوتاه تر است (حدود 100 میلی ثانیه). سپس با فونت جایگزین نمایش داده می شود و اگر فونت وب بعداً بارگذاری شد، سواپ می شود.optional
: مرورگر ابتدا متن را با فونت جایگزین نمایش می دهد و اگر فونت وب خیلی سریع بارگذاری شود، از آن استفاده می کند. در غیر این صورت، از فونت جایگزین استفاده می کند و فونت وب را برای بازدیدهای بعدی کش می کند. این گزینه تضمین می کند که هیچ CLS یا FOITی اتفاق نمی افتد، اما ممکن است فونت سفارشی برای برخی کاربران در بارگذاری اول نمایش داده نشود.
- مثال
@font-face
:
@font-face {
font-family: 'MyWebFont';
src: url('mywebfont.woff2') format('woff2');
font-display: swap; /* یا block, fallback, optional */
}
font-display
می تواند به کاهش یا حذف پدیده های FOIT و FOUT کمک کند و با کنترل زمان سواپ شدن فونت ها، تأثیر بر CLS را مدیریت کند. swap
اغلب تعادلی خوب بین تجربه بصری و عملکرد ارائه می دهد.ب) Preloading فونت ها
Preloading فونت ها به مرورگر کمک می کند تا فونت های ضروری را با اولویت بالا و در اسرع وقت دانلود کند، پیش از اینکه مرورگر آن ها را به طور طبیعی در فایل های CSS کشف کند.
- استفاده از
<link rel=preload as=font>
: این تگ باید در بخش<head>
سند HTML قرار گیرد.
<link rel=preload href=/fonts/myfont.woff2 as=font type=font/woff2 crossorigin>
- از Preload فقط برای فونت هایی استفاده کنید که برای محتوای بالای خط دید ضروری هستند. Preloading بیش از حد فونت ها می تواند به جای بهبود، عملکرد را کاهش دهد.
- ویژگی
crossorigin
برای فونت هایی که از دامنه دیگری (حتی CDN) بارگذاری می شوند، ضروری است. - با Preloading، فونت ها زودتر در دسترس قرار می گیرند و می توانند به کاهش FOIT و بهبود LCP کمک کنند.
تکنیک های Asynchronous Loading برای داده ها (AJAX/Fetch API)
بارگذاری ناهمزمان داده ها از سرور یکی از پایه های وب مدرن و تعاملی است. AJAX (Asynchronous JavaScript and XML) و به خصوص Fetch API، ابزارهای اصلی برای این کار هستند.
در گذشته، برای دریافت داده ها از سرور بدون رفرش کامل صفحه، از XMLHttpRequest (XHR) استفاده می شد که به AJAX معروف است. اما با ظهور Fetch API، این فرآیند ساده تر و مدرن تر شد.
Fetch API رابطی قدرتمند و انعطاف پذیر برای انجام درخواست های شبکه ارائه می دهد. این API مبتنی بر Promises است که مدیریت عملیات های ناهمزمان را آسان تر می کند.
برای مدیریت بهتر ناهمزمانی و خوانایی کد، می توان از کلمات کلیدی async/await
همراه با Fetch API استفاده کرد. این ترکیب به شما اجازه می دهد کد ناهمزمان را به شکلی بنویسید که شبیه کد سنکرون به نظر برسد، اما در واقعیت به صورت ناهمزمان اجرا شود.
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData();
در این مثال، await
تضمین می کند که خط بعدی کد تنها پس از کامل شدن Promise مربوط به fetch
و response.json()
اجرا می شود. این کار از Callback Hell جلوگیری کرده و کدی بسیار خواناتر ارائه می دهد. Fetch API و async/await
سنگ بنای برنامه های وب پویا و سریع هستند که داده ها را بدون وقفه در تجربه کاربری، از سرور دریافت می کنند.
نکات تکمیلی و بهترین شیوه ها
بهینه سازی بارگذاری یک فرآیند جامع است که فراتر از صرفاً پیاده سازی چند تکنیک خاص است. برای دستیابی به بهترین نتایج، باید به نکات تکمیلی و بهترین شیوه ها نیز توجه کرد.
تست و اندازه گیری عملکرد
تنها راه برای دانستن اینکه آیا تلاش های بهینه سازی شما موفق بوده اند، اندازه گیری مداوم عملکرد است. ابزارهای زیر در این زمینه بسیار کمک کننده هستند:
- Lighthouse: ابزار منبع باز گوگل که برای بررسی کیفیت صفحات وب، از جمله عملکرد، دسترسی پذیری، بهترین شیوه ها و سئو، استفاده می شود.
- PageSpeed Insights: ابزاری آنلاین از گوگل که عملکرد وب سایت شما را در دسکتاپ و موبایل تحلیل می کند و پیشنهاداتی برای بهبود ارائه می دهد، از جمله امتیازات Core Web Vitals.
- WebPageTest: ابزاری قدرتمند برای آزمایش عملکرد وب سایت در مرورگرهای مختلف، مکان های جغرافیایی متفاوت، و شرایط شبکه متنوع. این ابزار دید دقیقی از آبشارهای بارگذاری (Waterfall charts) و زمان بندی رندر ارائه می دهد.
یک توسعه دهنده باتجربه می داند که بهینه سازی یک فرآیند مستمر است و پس از هر تغییر، باید عملکرد را دوباره سنجید.
ابزارهای خودکارسازی (Webpack, Rollup)
مدیریت دستی تمامی تکنیک های بارگذاری ناهمزمان در پروژه های بزرگ می تواند طاقت فرسا باشد. ابزارهای باندلر (Bundler) مانند Webpack و Rollup به خودکارسازی این فرآیندها کمک می کنند:
- Code Splitting: این باندلرها می توانند کد جاوااسکریپت شما را به طور خودکار به بخش های کوچک تر تقسیم کنند که با Dynamic Imports سازگار هستند.
- Lazy Loading تصاویر و CSS: پلاگین هایی برای این ابزارها وجود دارند که می توانند Lazy Loading بومی یا مبتنی بر جاوااسکریپت را پیاده سازی کنند.
- Critical CSS Extraction: پلاگین هایی برای استخراج و اینلاین کردن Critical CSS در زمان بیلد (Build Time).
- Minification و Compression: کاهش حجم فایل ها که به طور غیرمستقیم به سرعت بارگذاری کمک می کند.
ترتیب بارگذاری صحیح دارایی ها
ترتیب بارگذاری دارایی ها می تواند تأثیر بسزایی بر عملکرد اولیه صفحه داشته باشد. یک استراتژی بهینه شامل موارد زیر است:
- CSS حیاتی (Critical CSS) را در بخش
<head>
و به صورت اینلاین قرار دهید. - فایل های CSS غیرحیاتی را به صورت ناهمزمان یا با
<link rel=preload>
بارگذاری کنید. - فونت های وب ضروری را با
<link rel=preload>
و با استفاده ازfont-display: swap;
بارگذاری کنید. - اسکریپت های جاوااسکریپت را تا حد امکان با
defer
یاasync
بارگذاری کنید و آن ها را در انتهای تگ<body>
یا در<head>
قرار دهید (با استفاده ازasync/defer
). - تصاویر و ویدئوهای پایین خط دید را با
loading=lazy
یا Intersection Observer بارگذاری کنید.
چالش ها و موارد احتیاط
پیاده سازی تکنیک های ناهمزمان همیشه بدون چالش نیست:
- وابستگی ها: مدیریت وابستگی ها بین اسکریپت ها و استایل ها می تواند پیچیده باشد. اگر اسکریپت A به اسکریپت B وابسته باشد و هر دو به صورت
async
بارگذاری شوند، ممکن است اسکریپت B قبل از A اجرا شود و منجر به خطا شود.defer
برای حفظ ترتیب مناسب تر است. - Flash of Unstyled Content (FOUC): اگر CSS به درستی مدیریت نشود، ممکن است برای لحظاتی صفحه بدون استایل نمایش داده شود و سپس به طور ناگهانی استایل ها اعمال شوند. Critical CSS و
font-display: swap
می توانند این مشکل را کاهش دهند. - پیچیدگی افزایش یافته: استفاده از تکنیک های پیشرفته ممکن است به کدنویسی و نگهداری پیچیده تر منجر شود.
تأثیر بر سئو و رتبه بندی
موتورهای جستجو، به ویژه گوگل، سرعت صفحه و تجربه کاربری را به عنوان فاکتورهای مهم در رتبه بندی در نظر می گیرند. وب سایت های سریع تر:
- احتمال بیشتری برای کراول شدن و ایندکس شدن دارند.
- امتیازات Core Web Vitals بهتری کسب می کنند که به طور مستقیم بر سئو تأثیرگذار است.
- نرخ خروج پایین تری دارند و زمان ماندگاری کاربران بالاتری را تجربه می کنند که این نیز سیگنالی مثبت برای موتورهای جستجو است.
از این رو، سرمایه گذاری در تکنیک های بارگذاری ناهمزمان، یک سرمایه گذاری مستقیم در سئوی وب سایت شما محسوب می شود.
نتیجه گیری
در دنیای امروز که سرعت حرف اول را می زند، استفاده از تکنیک های بارگذاری ناهمزمان دیگر یک انتخاب لوکس نیست، بلکه ضرورتی اجتناب ناپذیر برای هر وب سایتی است که می خواهد در رقابت باقی بماند. از اسکریپت های جاوااسکریپت با ویژگی های async
و defer
گرفته تا بهینه سازی CSS با Critical CSS و Lazy Loading تصاویر، هر تکنیک گامی است در جهت ساختن تجربه ای بی نقص و سریع برای کاربر.
تجربه نشان داده است که با به کارگیری این روش ها، نه تنها می توانید سرعت بارگذاری وب سایت خود را به شکل چشمگیری بهبود بخشید و امتیازات Core Web Vitals را ارتقا دهید، بلکه رضایت کاربران را افزایش داده و در نهایت، به جایگاه بهتری در نتایج موتورهای جستجو دست یابید. این مسیر شاید در ابتدا پیچیده به نظر برسد، اما با دانش و ابزارهای مناسب، دستیابی به وب سایتی بهینه و پرسرعت کاملاً امکان پذیر است. از همین امروز شروع کنید، وب سایت خود را تست کنید و با پیاده سازی این تکنیک ها، تفاوتی ملموس در عملکرد آن ایجاد نمایید.