مرورگر چگونه صفحه را می سازد
مرورگر HTML را از اولین بایت می خواند و همزمان درخت صفحه را می سازد، ولی تا وقتی CSS را نفهمیده باشد چیزی روی صفحه نمی کشد، و اگر به یک اسکریپت معمولی برسد همان جا می ایستد. هر توصیه ای درباره سرعت که در ادامه این مسیر می شنوید، از همین دو جمله بیرون می آید.
- درس ۲ از ۱۰
- مقدماتی
- رایگان، بدون ثبت نام
از رسیدن HTML تا اولین چیزی که می بینید
پنج قدم که مرورگر برای هر صفحه برمی دارد. سه قدم اول را می شود کند کرد و دو قدم آخر نتیجه اند.
-
۱
درخواست
تا اولین بایت HTML نرسد، مرورگر هیچ چیزی برای شروع ندارد.
-
۲
پارس و ساخت DOM
تدریجی پیش می رود و روی یک اسکریپت معمولی می ایستد.
-
۳
خواندن CSS
نقشه دوم ساخته می شود. تا این آماده نشود چیزی کشیده نمی شود.
-
۴
درخت رندر و چیدمان
دو نقشه یکی می شوند و جای هر چیزی روی صفحه حساب می شود.
-
۵
رنگ آمیزی
اولین چیزی که خواننده می بیند. هر تاخیری در سه قدم قبل، اینجا خودش را نشان می دهد.
این ترتیب ساده شده است. مرورگرهای واقعی بخشی از این قدم ها را همزمان و حدسی جلو می برند، و همین است که باعث می شود اثر یک تغییر همیشه به اندازه ای که از روی این شکل انتظار دارید نباشد.
آخرین بررسی: فکت ها و نام ابزارهای این درس در همین تاریخ با منابعشان بازبینی شده اند.
از لحظه ای که HTML می رسد چه اتفاقی می افتد
اولین چیزی که باید از ذهنتان بیرون کنید این است که مرورگر منتظر می ماند تا کل فایل برسد. نمی ماند. از همان اولین بایت شروع به خواندن می کند و همزمان که بقیه صفحه هنوز در راه است، دارد ساختار آن را می سازد.
کاری که می کند اسم دارد: پارس کردن. مرورگر بایت ها را به حرف، حرف ها را به نشانه هایی مثل «اینجا یک پاراگراف باز شد»، و آن نشانه ها را به گره تبدیل می کند. گره ها به هم وصل می شوند و یک درخت می سازند که به آن DOM می گویند، یعنی همان نقشه ای که مرورگر از ساختار صفحه شما در حافظه دارد. هر چیزی که بعدا جاوااسکریپت عوض می کند، روی همین درخت عوض می شود و نه روی فایل شما.
مهم ترین ویژگی این کار تدریجی بودنش است. مرورگر لازم ندارد صبر کند تا تگ پایانی برسد؛ اگر چیزی برای نشان دادن آماده باشد، نشان می دهد. به همین دلیل است که گاهی صفحه ای را می بینید که بالایش آمده و پایینش هنوز در حال آمدن است. سایت کند لزوما سایتی نیست که همه چیزش دیر می آید؛ اغلب سایتی است که چیزی جلوی همین شروع تدریجی را گرفته.
و دقیقا همین است که کل بحث سرعت را قابل فهم می کند. سوال درست «صفحه من چقدر سنگین است» نیست، «چه چیزی نگذاشت مرورگر زودتر شروع کند» است. دو بخش بعدی دو جواب اصلی این سوال اند.

چرا CSS نمایش را نگه می دارد ولی تصویر نگه نمی دارد
داشتن درخت صفحه برای کشیدن کافی نیست. مرورگر می داند اینجا یک تیتر هست، ولی نمی داند آن تیتر چه اندازه ای دارد، چه رنگی است و اصلا قرار است دیده شود یا نه. این را از CSS می فهمد و از روی آن یک نقشه دوم می سازد که به آن CSSOM می گویند. تازه وقتی هر دو نقشه آماده شد، مرورگر می تواند درخت رندر را بسازد و بکشد.
پس چرا صبر می کند؟ چون گزینه دیگر بدتر است. اگر متن را قبل از آماده شدن CSS بکشد، شما یک لحظه متن بی قواره سیاه روی سفید می بینید و بلافاصله بعدش همه چیز جابه جا می شود. مرورگرها این را تجربه بدتری از کمی صبر کردن می دانند، برای همین CSS به طور پیش فرض نمایش را مسدود می کند. این یک نقص نیست، یک تصمیم است.
حالا تفاوتی که خیلی ها را گیر می اندازد: تصویر این کار را نمی کند. اگر عکسی هنوز نیامده باشد، ظاهر متن عوض نمی شود، پس مرورگر دلیلی ندارد که منتظرش بماند؛ صفحه را می کشد و عکس بعدا سر جایش می نشیند. البته اگر برای آن عکس جا رزرو نکرده باشید، وقتی برسد بقیه محتوا را هل می دهد و همان پرشی اتفاق می افتد که خواننده از همه چیز بیشتر اذیتش می کند.
یک نمونه عملی که می توانید همین حالا چک کنید: صفحه اول همین سایت هیچ تگ link rel=stylesheet ندارد. کل CSS قالب داخل خود پاسخ HTML فرستاده می شود، یعنی برای اولین نمایش هیچ رفت و برگشتی به شبکه لازم نیست. این تنها راه درست نیست و هزینه خودش را هم دارد، ولی نشان می دهد که «فایل CSS را بهینه کنیم» تنها گزینه روی میز نیست.
جاوااسکریپت کجای این مسیر می ایستد
وقتی پارسر به یک تگ script معمولی می رسد، خواندن HTML را متوقف می کند، فایل را می گیرد، اجرا می کند و تازه بعد ادامه می دهد. تا وقتی این اتفاق می افتد، هیچ گره جدیدی به درخت اضافه نمی شود؛ یعنی بقیه صفحه، هر چقدر هم آماده باشد، منتظر است.
دلیلش منطقی است. اسکریپت اجازه دارد همان لحظه داخل صفحه بنویسد یا درخت را عوض کند، و مرورگر از قبل نمی داند که این اسکریپت چنین کاری می کند یا نه. پس محتاطانه ترین کار را می کند و صبر می کند. یک نکته کمتر گفته شده هم هست: اسکریپتی که در head نشسته ممکن است علاوه بر پارسر، منتظر CSS هم بماند، چون می تواند بپرسد یک عنصر الان چه اندازه ای دارد و مرورگر تا CSSOM آماده نشود نمی تواند جوابش را بدهد.
دو کلمه این وضع را عوض می کنند. defer به مرورگر می گوید فایل را همین حالا و به موازات خواندن HTML بگیر، ولی اجرایش را بگذار برای بعد از تمام شدن پارس، و ترتیب اسکریپت ها را هم حفظ کن. async می گوید بگیر و هر وقت رسید همان جا اجرا کن، بدون هیچ تضمینی درباره ترتیب. برای تقریبا هر اسکریپتی که به صفحه شما مربوط است، defer جواب درست است؛ async برای چیزهای مستقلی مثل آمارگیر منطقی است که به بقیه کد کاری ندارند.
و اینجا همان جایی است که سنگین بودن فایل گمراهتان می کند. یک عکس دو مگابایتی که پایین صفحه است هیچ چیزی را نگه نمی دارد. یک اسکریپت چهار کیلوبایتی که در head بدون defer نشسته و از سرور شخص ثالثی می آید که شما کنترلش نمی کنید، اولین نمایش کل صفحه را به اندازه یک رفت و برگشت کامل به آن سرور عقب می اندازد. حجم اهمیت دارد، ولی جای قرار گرفتن بیشتر.
یک اسکریپت، دو جای متفاوت در مسیر
همان فایل، همان حجم. تنها فرق یک کلمه است و آن کلمه تعیین می کند خواننده چه زمانی چیزی می بیند.
اسکریپت معمولی در head
- پارسر همان جا می ایستد و درخت صفحه جلو نمی رود
- اگر فایل از سرور دیگری بیاید، به اندازه یک رفت و برگشت کامل صبر می شود
- ممکن است علاوه بر پارسر، منتظر آماده شدن CSS هم بماند
- خواننده تا آخر این ماجرا صفحه سفید می بیند
همان اسکریپت با defer
- دانلود همان لحظه و به موازات خواندن HTML شروع می شود
- پارسر نمی ایستد و درخت صفحه کامل می شود
- اجرا بعد از پارس انجام می شود و ترتیب اسکریپت ها حفظ می ماند
- خواننده صفحه را می بیند در حالی که آن فایل هنوز در راه است
یک استثنای واقعی هست: اسکریپتی که باید قبل از اولین رنگ آمیزی اجرا شود، مثل تعیین تم روشن یا تیره، عمدا مسدودکننده می ماند تا صفحه یک لحظه سفید و بعد تیره نشود.
پس «اول CSS بعد جاوااسکریپت» خرافه نیست
این توصیه قدیمی است و در بیشتر جاهایی که تکرار می شود، دلیلش را غلط می گویند. دلیل واقعی این نیست که جاوااسکریپت سنگین است. دلیلش این است که نمایش منتظر CSS می ماند، پس CSS باید زود برسد؛ و پارسر منتظر اسکریپت می ماند، پس اسکریپت نباید وسط راه بایستد. یک جمله درباره ترتیب دو منتظر ماندن است، نه درباره وزن فایل ها.
روی صفحه اول همین سایت این ترتیب را می شود شمرد. در head صفر اسکریپت هست. هفت تگ اسکریپت روی صفحه وجود دارد و هر هفت تا در سه درصد آخر سند نشسته اند، یعنی بعد از تمام محتوایی که خواننده قرار است ببیند. CSS هم اصلا فایل جدا نیست و داخل خود پاسخ آمده. نتیجه اش این است که برای اولین نمایش، مرورگر منتظر هیچ چیزی از شبکه نمی ماند.
حالا صادقانه ترین بخش این درس: چیدمان بالا شکل قدیمی حل مسئله است. گذاشتن اسکریپت در انتهای بدنه کار می کند چون وقتی پارسر به آن می رسد، همه چیز را قبلا ساخته. ولی امروز شکل بهتر معمولا این است که همان اسکریپت را با defer در head بگذارید، چون آن وقت دانلودش زودتر شروع می شود و اجرایش باز هم آخر می افتد. ما این تغییر را روی این سایت هنوز نداده ایم؛ سودش کوچک است و روی صفحه ای که اسکریپت هایش تا این حد عقب اند، ارزش ریسک تغییر را نداشته.
و مرزی که باید بدانید: چند اسکریپت واقعا باید قبل از اولین رنگ آمیزی اجرا شوند، مثل تکه کدی که تم روشن یا تیره را تعیین می کند تا صفحه یک لحظه سفید و بعد تیره نشود. آن یکی را عمدا مسدودکننده نگه می دارند و این تصمیم درستی است. قاعده «همه را عقب بینداز» یک استثنا دارد و همین است.
چه چیزی اولین نمایش را نگه می دارد و چه چیزی فقط سنگین است
اینها نمایش را نگه نمی دارند
- تصویرها، هر چقدر هم بزرگ باشند
- اسکریپت هایی که با defer یا async مشخص شده اند
- CSS ای که داخل خود پاسخ HTML فرستاده شده
اینها نمایش را نگه می دارند
- هر فایل CSS که در head به صفحه وصل شده
- هر اسکریپت در head که نه defer دارد نه async
- اسکریپتی که از دامنه شخص ثالث می آید و در head نشسته
ستون راست یعنی این چیزها اولین نمایش را نگه نمی دارند، نه اینکه بی هزینه اند. یک عکس بزرگ بدون جای رزرو شده، وقتی برسد محتوا را جابه جا می کند و آن مشکل دیگری است.
این را روی سایت خودتان چطور ببینید
برای این کار به هیچ ابزاری احتیاج ندارید. سورس صفحه را باز کنید و فقط داخل head را نگاه کنید. دو چیز را بشمارید: چند تگ link rel=stylesheet هست، و چند تگ script با src که نه defer دارند و نه async. جمع این دو عدد، فهرست چیزهایی است که اولین نمایش صفحه شما را نگه داشته اند. اگر عدد دوم صفر نیست، معمولا اولین و ارزان ترین کار همان جاست.
اگر ترجیح می دهید از خط فرمان این کار را بکنید، این دستور همان تگ ها را چاپ می کند تا خودتان ببینید کدامشان defer یا async دارد:
curl -s https://example.com/ | tr '\n' ' ' | sed 's/<\/head>.*//' | grep -oE '<link[^>]*stylesheet[^>]*>|<script[^>]*src=[^>]*>'نسخه ساده تر همین دستور که محدوده head را خط به خط با sed جدا می کند، روی صفحه های فشرده شده جواب غلط می دهد و ما خودمان سرش وقت گذاشتیم. HTML فشرده معمولا یک خط بلند است، پس آن محدوده تا آخر سند باز می ماند و اسکریپت های انتهای بدنه را هم به حساب می آورد. دستور بالا اول هر چه بعد از </head> است را دور می ریزد و به همین دلیل روی هر دو حالت درست کار می کند.
یک هشدار درباره تفسیر نتیجه: مرورگرهای امروزی یک اسکنر جداگانه دارند که وقتی پارسر اصلی روی یک اسکریپت ایستاده، جلوتر را نگاه می کند و فایل های بعدی را زودتر شروع به گرفتن می کند. یعنی «پارسر می ایستد» به معنای «شبکه هم بیکار می ماند» نیست. این یکی از دلایلی است که چرا حذف یک اسکریپت مسدودکننده گاهی کمتر از انتظار اثر می گذارد، و چرا اندازه گیری قبل و بعد را نمی شود با استدلال جایگزین کرد.
و قدم بعدی همین است: تا اینجا فهمیدید چه چیزی می تواند نمایش را نگه دارد، ولی نمی دانید روی سایت شما کدامشان واقعا این کار را کرده و چقدر. آن سوال با اندازه گیری جواب می گیرد و درس اندازه گیری سرعت سایت در همین مسیر به آن می پردازد. اگر هم می خواهید همین حالا یک عدد واقعی از صفحه تان داشته باشید، ابزار تست سرعت روی صفحه افزایش سرعت سایت با موتور Lighthouse کار می کند.
مسیر سریع با هوش مصنوعی
وقتی صفحه ای کند است، کار معمولی این است که نمودار آبشاری را در ابزار توسعه دهنده باز کنید و دنبال بلندترین میله بگردید. مشکل اینجاست که بلندترین میله معمولا مقصر نیست؛ مقصر آن چیزی است که بقیه منتظرش مانده اند، و آن اغلب یک میله کوتاه در ابتدای نمودار است. مدل زبانی دقیقا در همین جور خواندنی خوب است: چند ده ردیف زمان بندی را با هم می بیند و الگوی «این منتظر آن بوده» را زودتر از چشم شما پیدا می کند. کل کار ده دقیقه است و شرط اولش این است که فایل خام را جلوی مدل نگذارید.
- در مرورگر، ابزار توسعه دهنده را باز کنید، به تب شبکه بروید، کش را غیرفعال کنید و صفحه را یک بار کامل بارگذاری کنید. خروجی را به صورت HAR ذخیره کنید.
- فایل HAR را همان طور که هست هیچ جا نچسبانید. آن فایل تمام هدرهای درخواست را در خود دارد، یعنی کوکی های ورود و توکن های نشست شما هم داخلش هستند. فقط پنج ستون را بیرون بکشید: نشانی، نوع فایل، لحظه شروع، مدت، و اینکه در head بوده یا نه. اگر پنجاه ردیف اول را بردارید کافی است.
- جدول را با دستور زیر بدهید و صریح بخواهید که بین دو چیز فرق بگذارد: فایلی که خودش طول کشیده، و فایلی که دیر شروع شده چون منتظر چیز دیگری بوده. تمام ارزش این کار در همین تفکیک است. برای این کار یک مدل قوی لازم است چون قضاوت می خواهد؛ انتخاب امروزی هر رده در مرجع هوش مصنوعی ما نگهداری می شود.
- جواب را باور نکنید، امتحانش کنید. فقط یک چیز را عوض کنید، همان که مدل اسم برده، و دوباره اندازه بگیرید. اگر عدد تکان نخورد، فرضیه غلط بوده و این هم یک نتیجه است. دو تغییر با هم یعنی هیچ وقت نمی فهمید کدامشان کار کرد.
نسخه آماده کپی
نقش تو کارشناس عملکرد وب است. فقط از روی جدول زیر قضاوت کن و هیچ چیزی درباره این سایت از حافظه ات اضافه نکن.
جدول زیر از یک بار بارگذاری کامل صفحه {نشانی صفحه} گرفته شده. برای هر منبع: نشانی، نوع، لحظه شروع بر حسب میلی ثانیه از ابتدای بارگذاری، مدت بر حسب میلی ثانیه، و اینکه در head بوده یا نه.
{جدول منابع}
پنج چیز بنویس:
۱. منابعی را که می توانستند اولین نمایش را نگه دارند جدا کن: فقط CSS و اسکریپت بدون defer یا async که در head بوده اند. بقیه را کنار بگذار و بگو چرا کنار گذاشتی.
۲. برای هر کدام از آنها بگو کدام حالت است: خودش طول کشیده، یا دیر شروع شده چون منتظر منبع دیگری بوده. برای حالت دوم اسم آن منبع دیگر را بگو.
۳. یک منبع را نام ببر که به احتمال زیاد بیشترین تاخیر را روی اولین نمایش گذاشته، و در یک جمله بگو از روی کدام ستون های جدول به این نتیجه رسیدی.
۴. یک تغییر مشخص پیشنهاد بده که بشود آن را تنها انجام داد و بعد اندازه گرفت.
۵. بنویس چه چیزی در این جدول نیست که اگر بود جوابت می توانست عوض شود.
قاعده ها: هیچ عددی که در جدول نیست نساز و هیچ منبعی را که در جدول نیست فرض نکن. حجم فایل به تنهایی دلیل مسدود کردن نیست؛ اگر می خواهی به حجم استناد کنی، بگو چرا در این مورد مهم است. اگر جدول برای نتیجه گیری کافی نیست، همین را بنویس و به جایش بگو چه ستونی لازم داری. جواب «هیچ منبع مسدودکننده ای در head نبود» جواب قابل قبولی است.
قبل از اعتماد به خروجی: یک محدودیت ذاتی هست که با هیچ مدلی برطرف نمی شود: نمودار آبشاری می گوید چه چیزی کی اتفاق افتاده، نه اینکه چرا. ترتیب زمانی شبیه علت است و علت نیست، و مدل هم دقیقا همین ترتیب را می بیند. پس خروجی این کار یک فرضیه است و نه یک تشخیص؛ تنها چیزی که آن را به تشخیص تبدیل می کند، عوض کردن همان یک چیز و اندازه گیری دوباره است. و یک نکته که در همین درس هم آمد: مرورگرها جلوتر از پارسر فایل ها را حدسی شروع به گرفتن می کنند، پس گاهی حذف یک اسکریپت مسدودکننده کمتر از چیزی که نمودار نشان می دهد اثر می گذارد. اگر عدد بعد از تغییر تکان نخورد، این شکست شما نیست؛ همان اندازه گیری است که کارش را کرده.
هوش مصنوعی در این کار
در این موضوع مدل زبانی دو رفتار کاملا متفاوت دارد و فرقشان همان چیزی است که تعیین می کند وقتتان هدر می رود یا نه. اگر جدول زمان بندی واقعی صفحه تان را جلویش بگذارید، عالی است: چند ده ردیف را با هم می بیند و رابطه انتظار بین آنها را زودتر از شما پیدا می کند. اگر چیزی جلویش نگذارید و فقط بپرسید چطور سایتم را سریع کنم، فهرست عمومی همیشگی را می گیرید که برای هر سایتی نوشته شده و برای هیچ سایتی دقیق نیست.
ابزارهایی که واقعا کمک می کنند
- Claude برای همان کار مسیر سریع مناسب است: جدول را می گیرد و به جای فهرست کردن همه چیز، یک منبع را نام می برد و می گوید از کدام ستون به آن رسیده. ایران در فهرست کشورهای پشتیبانی شده انتروپیک نیست، پس راه رسمی ثبت نام و پرداخت وجود ندارد.
- Gemini اگر جدول شما بزرگ است و ترجیح می دهید ردیف ها را کم نکنید، خواندن ورودی های طولانی را خوب انجام می دهد. ایران در فهرست مناطقی که این سرویس در دسترس است نیست.
- OpenAI رایج ترین انتخاب و برای خواندن یک جدول پنجاه ردیفی کافی. درباره دسترسی و پرداخت از ایران ادعایی نمی کنیم و لینک به صفحه سازنده است نه صفحه محصول: هیچ صفحه مصرفی اوپن ای آی از این سرور باز نمی شود و ما درباره چیزی که خودمان نتوانسته ایم ببینیم چیزی نمی نویسیم.
کجا نتیجه معکوس می دهد
دو خطر، و اولی مخصوص همین موضوع است. مدل به شدت تمایل دارد بزرگ ترین فایل را مقصر معرفی کند، چون در متنی که رویش آموزش دیده، سنگین بودن و کند بودن تقریبا مترادف اند. ولی همان طور که در این درس دیدید، مسدود کردن به جای قرار گرفتن و نوع منبع مربوط است و نه به حجم: یک عکس بزرگ پایین صفحه هیچ چیزی را نگه نمی دارد و یک اسکریپت کوچک در head همه چیز را نگه می دارد. اگر جواب مدل فقط بزرگ ترین ردیف جدول را نام برد، احتمالا از الگو جواب داده و نه از داده شما. خطر دوم امنیتی است و جبران ناپذیرتر: فایل HAR تمام هدرهای درخواست را در خود دارد، یعنی کوکی های ورود و توکن های نشست. چسباندن آن فایل به صورت خام در هر ابزار آنلاینی، در عمل یعنی فرستادن کلید حساب شما به یک سرویس بیرونی، و انتروپیک هم در راهنمای امنیتی خودش می گوید هر چیزی که وارد پنجره متن می شود باید مثل ورودی غیرقابل اعتماد با آن رفتار شود. موضع ما: جدول را با دست به پنج ستون کم کنید، و هر منبعی را که مدل نام برد قبل از باور کردن یک بار خودتان تغییر بدهید و اندازه بگیرید.
منبع ها: MDN: critical rendering path MDN: the script element, defer and async Anthropic: mitigate jailbreaks and prompt injections Anthropic: supported countries Google: where Gemini Apps are available
حد این توصیه
این تصویر پنج قدمی مسیر کلاسیک است و برای فهمیدن کافی است، ولی دو جا از واقعیت عقب می ماند. اول اینکه مرورگرهای امروزی این قدم ها را دقیقا پشت سر هم انجام نمی دهند: یک اسکنر جداگانه جلوتر از پارسر می رود و فایل های بعدی را حدسی شروع به گرفتن می کند، بخشی از چیدمان و رنگ آمیزی موازی انجام می شود، و به همین دلیل اثر یک تغییر همیشه به اندازه ای نیست که از روی این نمودار انتظار دارید. دوم و مهم تر: اگر سایت شما تک صفحه ای است و محتوا را خود جاوااسکریپت در مرورگر می سازد، این تصویر فقط شروع ماجرا را توضیح می دهد. آنجا اولین رنگ آمیزی ممکن است سریع اتفاق بیفتد و صفحه همچنان خالی باشد، و وقت واقعی جای دیگری می رود که این درس به آن نمی پردازد.
از تجربه خود ما
اعداد این درس از صفحه اول همین سایت در ۱۶ شهریور ۱۴۰۵ آمده و هر کدام با دیدن سورس صفحه قابل بررسی است: صفر تگ link rel=stylesheet، صفر اسکریپت در head، و هفت تگ اسکریپت که هر هفت تا در سه درصد آخر سند نشسته اند. کل CSS قالب حدود ۹۱ کیلوبایت است و داخل خود پاسخ HTML فرستاده می شود. حالا چیزی که واقعا موقع نوشتن همین درس یاد گرفتیم و ارزشش از آن اعداد بیشتر است: نسخه اول دستوری که در بخش پنجم آمد با sed محدوده head را خط به خط جدا می کرد، و روی همین صفحه جواب غلط داد. HTML این سایت فشرده است و تقریبا یک خط بلند، پس آن محدوده هیچ وقت بسته نشد و تا آخر سند ادامه پیدا کرد؛ نتیجه اش این بود که همان هفت اسکریپت انتهای بدنه را به عنوان اسکریپت داخل head شمرد. اگر آن دستور را قبل از امتحان کردن منتشر کرده بودیم، به هر کسی که سایتش کش دارد جواب غلط می داد، و دقیقا همان اشتباهی می شد که این درس درباره اش هشدار می دهد: استدلال درست روی داده ای که خودتان چک نکرده اید.
سوال هایی که واقعا پرسیده می شوند
چرا صفحه ام یک لحظه بدون استایل نشان داده می شود؟
چون بخشی از CSS شما به شکلی بارگذاری می شود که نمایش را مسدود نمی کند، مثلا با جاوااسکریپت یا با ترفندهایی که فایل استایل را غیرمسدودکننده می کنند. مرورگر صبر نمی کند، متن را می کشد و بعد استایل می رسد و همه چیز جابه جا می شود. راه حل این است که استایل های لازم برای همان بخش اول صفحه به شکل معمولی و مسدودکننده بیایند و بقیه بعدا.
اگر همه اسکریپت ها را defer کنم چیزی خراب می شود؟
ممکن است، و معمول ترین حالتش این است که یک تکه کد درون خطی داخل صفحه به کتابخانه ای وابسته باشد که حالا دیرتر اجرا می شود. کد درون خطی از قاعده defer پیروی نمی کند و سر جای خودش اجرا می شود، پس ترتیب به هم می خورد و خطای «فلان چیز تعریف نشده» می گیرید. یکی یکی جلو بروید و بعد از هر تغییر صفحه را واقعا باز کنید و کنسول خطا را نگاه کنید.
پس بهتر است CSS را مثل شما داخل صفحه بگذارم؟
نه لزوما، و این یک معامله است نه یک بهبود خالص. اینلاین کردن یک رفت و برگشت شبکه را حذف می کند، ولی همان بایت ها در هر پاسخ دوباره فرستاده می شوند و دیگر بین صفحه ها کش نمی شوند. برای ما می ارزد چون HTML این سایت روی لبه کش می شود و بازدیدکننده معمولا چند صفحه را پشت سر هم باز نمی کند؛ اگر سایت شما پویاست و کاربر ده صفحه را دنبال هم می بیند، فایل جدا و کش شده احتمالا انتخاب بهتری است.