Don't fight the browser preload scanner

ببینید اسکنر پیش‌بارگذاری مرورگر چیست، چگونه به عملکرد کمک می‌کند، و چگونه می‌توانید از سر راه آن کنار بروید.

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

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

اسکنر پیش‌بارگیری چیست؟

هر مرورگر یک تجزیه‌کننده HTML اصلی دارد که نشانه‌گذاری خام را نشانه‌گذاری می‌کند و آن را به یک مدل شیء پردازش می‌کند. این روند به‌خوبی ادامه می‌یابد تا زمانی که تجزیه‌کننده با یک منبع مسدودکننده مواجه شود و متوقف شود، مانند یک برگه سبک نگارش که با عنصر <link> بارگذاری شده است، یا یک دستورگان که با عنصر <script> بدون مشخصه async یا defer بارگذاری شده است.

نمودار تجزیه‌کننده HTML.
شکل ۱: نموداری از نحوه مسدود شدن تجزیه‌کننده HTML اصلی مرورگر. دراین‌صورت، تجزیه‌کننده به عنصر <link> برای فایل CSS خارجی می‌رسد که مرورگر را از تجزیه بقیه سند (یا حتی رندر کردن هر بخشی از آن) تا زمانی که CSS بارگیری و تجزیه شود، بازمی‌دارد.

در مورد فایل‌های CSS، پرداز زدن برای جلوگیری از فلش محتوای بدون سبک (FOUC) مسدود می‌شود، یعنی زمانی که نسخه بدون سبک صفحه را می‌توان به‌طور خلاصه قبل‌از اعمال سبک‌ها به آن مشاهده کرد.

صفحه اصلی web.dev در حالت بدون سبک (چپ) و حالت سبک‌دار (راست).
شکل ۲: نمونه شبیه‌سازی‌شده‌ای از FOUC. در سمت راست، صفحه اول web.dev بدون سبک‌ها نشان داده شده است. در سمت چپ، همان صفحه با سبک‌های اعمال‌شده نشان داده شده است. اگر مرورگر درحین بارگیری و پردازش برگه سبک نگارش، رندر کردن را مسدود نکند، حالت بدون سبک می‌تواند در یک لحظه رخ دهد.

مرورگر همچنین تجزیه و رندر صفحه را هنگام مواجهه با عناصر <script> بدون مشخصه defer یا async مسدود می‌کند.

دلیل این امر این است که مرورگر نمی‌تواند مطمئن باشد که آیا یک اسکریپت خاص DOM را تغییر می‌دهد یا نه، درحالی‌که تجزیه‌کننده اصلی HTML هنوز درحال انجام کار خود است. به همین دلیل است که بار کردن جاوا اسکریپت در انتهای سند به یک روش معمول تبدیل شده است تا تأثیرات تجزیه و پردازش مسدودشده حاشیه‌ای شود.

این‌ها دلایل خوبی هستند که چرا مرورگر باید هم تجزیه و هم پردازش را مسدود کند. بااین‌حال، مسدود کردن هریک از این مراحل مهم نامطلوب است، زیرا می‌تواند با به‌تأخیر انداختن کشف منابع مهم دیگر، نمایش را متوقف کند. خوشبختانه مرورگرها تمام تلاش خود را می‌کنند تا این مشکلات را ازطریق تجزیه‌کننده HTML ثانویه به‌نام اسکنر پیش‌بارگیری کاهش دهند.

نموداری از تجزیه‌کننده HTML اصلی (سمت راست) و اسکنر پیش‌بارگیری (سمت چپ) که تجزیه‌کننده HTML ثانویه است.
شکل ۳: نموداری که نشان می‌دهد چگونه اسکنر پیش‌بارگیری به‌موازات تجزیه‌کننده اصلی HTML کار می‌کند تا دارایی‌ها را به‌صورت گمانه‌زنی بارگیری کند. در اینجا، تجزیه‌کننده اصلی HTML مسدود شده است زیرا CSS را قبل‌از اینکه بتواند پردازش نشان‌گذاری تصویر را در عنصر <body> شروع کند بارگیری و پردازش می‌کند، اما اسکنر پیش‌بارگیری می‌تواند در نشان‌گذاری خام جلوتر را نگاه کند تا آن منبع تصویر را پیدا کند و بارگیری آن را قبل‌از رفع انسداد تجزیه‌کننده اصلی HTML شروع کند.

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

چگونه متوجه شویم که اسکنر پیش‌بارگیری درحال کار است

اسکنر پیش‌بارگذاری به‌دلیل تجزیه و پردازش مسدودشده وجود دارد. اگر این دو مشکل عملکرد وجود نداشت، اسکنر پیش‌بارگذاری چندان مفید نبود. کلید فهمیدن اینکه آیا صفحه وب از اسکنر پیش‌بارگیری بهره می‌برد یا نه به این پدیده‌های مسدودسازی بستگی دارد. برای انجام این کار، می‌توانید یک تأخیر مصنوعی برای درخواست‌ها ایجاد کنید تا متوجه شوید اسکنر پیش‌بارگذاری کجا کار می‌کند.

برای مثال، این صفحه از نوشتار و تصاویر پایه را با برگه سبک نگارش درنظر بگیرید. چون فایل‌های CSS هم تجزیه و هم پردازش را مسدود می‌کنند، ازطریق یک پیشکار، تأخیر مصنوعی دو ثانیه‌ای برای برگه سبک نگارش ایجاد می‌کنید. این تأخیر باعث می‌شود که در آبشار شبکه راحت‌تر بتوان دید که اسکنر پیش‌بارگذاری کجا کار می‌کند.

نمودار آبشاری شبکه WebPageTest تأخیر مصنوعی ۲ ثانیه‌ای را نشان می‌دهد که بر styleesheet تحمیل شده است.
شکل ۴: نمودار آبشاری شبکه WebPageTest از صفحه وب اجراشده در Chrome در دستگاه همراه ازطریق اتصال 3G شبیه‌سازی‌شده. باوجود اینکه برگه سبک نگارش به‌طور مصنوعی ازطریق پراکسی دو ثانیه قبل‌از شروع بارگیری به‌تأخیر می‌افتد، تصویری که بعداً در محموله نشان‌گذاری قرار می‌گیرد توسط اسکنر پیش‌بارگیری کشف می‌شود.

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

با کنار گذاشتن این مثال اسباب‌بازی، بیایید نگاهی به برخی الگوهای دنیای واقعی بیندازیم که در آن اسکنر پیش‌بارگذاری می‌تواند شکست بخورد - و چه کاری می‌توان برای رفع آن‌ها انجام داد.

‫async دستورگان تزریق‌شده

فرض کنید در <head> خود HTML دارید که شامل جاوا اسکریپت درون‌خطی مانند این است:

<script>
  const scriptEl = document.createElement('script');
  scriptEl.src = '/yall.min.js';

  document.head.appendChild(scriptEl);
</script>

اسکریپت‌های تزریق‌شده به‌طور پیش‌فرض async هستند، بنابراین وقتی این اسکریپت تزریق می‌شود، طوری رفتار می‌کند که گویی مشخصه async به آن اعمال شده است. یعنی در اسرع وقت اجرا می‌شود و پردازش را مسدود نمی‌کند. به‌نظر عالی می‌رسد، نه؟ بااین‌حال، اگر فرض کنید که این <script> درون‌خطی بعداز عنصر <link> که فایل CSS خارجی را بار می‌کند می‌آید، نتیجه‌ای کمتر از حد مطلوب دریافت خواهید کرد:

این نمودار WebPageTest نشان می‌دهد که وقتی اسکریپتی تزریق می‌شود، اسکن پیش‌بارگذاری شکست می‌خورد.
شکل ۵: نمودار آبشاری شبکه WebPageTest از یک صفحه وب که در Chrome در دستگاه همراه ازطریق اتصال 3G شبیه‌سازی‌شده اجرا می‌شود. صفحه حاوی یک برگه سبک نگارش و یک متن async تزریق‌شده است. اسکنر پیش‌بارگذاری نمی‌تواند اسکریپت را درطول مرحله مسدود کردن رندر کشف کند، زیرا در کارخواه تزریق شده است.

بیایید آنچه را اتفاق افتاده است بررسی کنیم:

  1. در ثانیه ۰، سند اصلی درخواست می‌شود.
  2. در ثانیه ۱٫۴، اولین بایت درخواست پیمایش می‌رسد.
  3. در ثانیه ۲٫۰، CSS و تصویر درخواست می‌شوند.
  4. ازآنجایی‌که تجزیه‌کننده در بار کردن برگه سبک نگارش مسدود شده است و جاوا اسکریپت درون‌خطی که دستورگان async را تزریق می‌کند بعداز آن برگه سبک نگارش در ثانیه ۲٫۶ می‌آید، عملکردی که دستورگان ارائه می‌دهد در اولین زمان ممکن دردسترس قرار نمی‌گیرد.

این حالت بهینه نیست زیرا درخواست برای اسکریپت فقط پس‌از اتمام بارگیری برگه سبک نگارش رخ می‌دهد. این کار باعث می‌شود دستورگان در اولین فرصت ممکن اجرا نشود. درمقابل، چون عنصر <img> در نشان‌گذاری ارائه‌شده توسط سرور قابل‌شناسایی است، توسط اسکنر پیش‌بارگذاری شناسایی می‌شود.

بنابراین، اگر از برچسب <script> معمولی با مشخصه async به‌جای تزریق کردن دستورگان به DOM استفاده کنید چه اتفاقی می‌افتد؟

<script src="/yall.min.js" async></script>

نتیجه این است:

یک آبشار شبکه WebPageTest که نشان می‌دهد چگونه یک اسکریپت ناهمگام بارگذاری‌شده بااستفاده از عنصر اسکریپت HTML هنوز توسط اسکنر پیش‌بارگذاری مرورگر قابل‌شناسایی است، حتی اگر تجزیه‌کننده HTML اصلی مرورگر درحین بارگیری و پردازش یک برگه سبک نگارش مسدود شده باشد.
شکل ۶: نمودار آبشاری شبکه WebPageTest یک صفحه وب که در Chrome در دستگاه همراه ازطریق اتصال 3G شبیه‌سازی‌شده اجرا می‌شود. صفحه حاوی یک برگه سبک نگارش و یک عنصر async <script> است. اسکنر پیش‌بارگیری متن را درطول مرحله مسدود کردن رندر پیدا می‌کند و آن را هم‌زمان با CSS بار می‌کند.

ممکن است این وسوسه وجود داشته باشد که این مشکلات را می‌توان بااستفاده از rel=preload برطرف کرد. این کار قطعاً مؤثر است، اما ممکن است عوارض جانبی داشته باشد. به‌هرحال، چرا از rel=preload برای رفع مشکلی استفاده کنیم که می‌توان با تزریق نکردن عنصر <script> به DOM از آن جلوگیری کرد؟

آبشار WebPageTest نشان می‌دهد که چگونه از اشاره منبع rel=preload برای ترویج کشف یک اسکریپت تزریق‌شده ناهمگام استفاده می‌شود—البته به روشی که ممکن است عوارض جانبی ناخواسته‌ای داشته باشد.
شکل ۷: نمودار آبشاری شبکه WebPageTest از یک صفحه وب که در Chrome روی یک دستگاه همراه ازطریق اتصال 3G شبیه‌سازی‌شده اجرا می‌شود. صفحه حاوی یک برگه سبک نگارش و یک اسکریپت async تزریق‌شده است، اما اسکریپت async ازپیش بار شده است تا اطمینان حاصل شود که زودتر کشف می‌شود.

پیش‌بارگیری مشکل را در اینجا «برطرف می‌کند»، اما مشکل جدیدی ایجاد می‌کند: اسکریپت async در دو نسخه نمایشی اول—باوجود بارگیری در <head>—با اولویت «پایین» بارگیری می‌شود، درحالی‌که برگه سبک نگارش با اولویت «بالاترین» بارگیری می‌شود. در آخرین نسخه نمایشی که در آن اسکریپت async ازپیش بار شده است، برگه سبک نگارش همچنان با اولویت «بالاترین» بار می‌شود، اما اولویت اسکریپت به «بالا» ارتقا یافته است.

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

پاسخ در اینجا ساده است: اگر درطول راه‌اندازی به اسکریپت نیاز است، با تزریق آن به DOM، اسکنر پیش‌بارگیری را ازکار نیندازید. درصورت نیاز، با جای‌گذاری عنصر <script> و همچنین با مشخصه‌هایی مثل defer و async آزمایش کنید.

بارکردن کُند با جاوا اسکریپت

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

این امر باعث ایجاد مشکلات احتمالی در قابلیت کشف منبع در جایی می‌شود که اسکنر پیش‌بارگیری درگیر است و می‌تواند به‌طور غیرضروری مدت‌زمان لازم برای کشف ارجاع به تصویر، بارگیری آن، رمزگشایی آن، و ارائه آن را به تأخیر بیندازد. بیایید این نشانه‌گذاری تصویر را به‌عنوان مثال درنظر بگیریم:

<img data-src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">

استفاده از پیشوند data- الگویی رایج در بارگذارهای تنبل مبتنی بر جاوا اسکریپت است. وقتی تصویر به نمای دید پیمایش می‌شود، بارکننده تنبل پیشوند data- را حذف می‌کند، یعنی در مثال قبلی، data-src به src تبدیل می‌شود. این به‌روزرسانی مرورگر را ترغیب می‌کند تا منبع را واکشی کند.

این الگو تا زمانی که روی تصاویر موجود در نمای پورت درطول راه‌اندازی اعمال نشود، مشکل‌ساز نیست. چون اسکنر پیش‌بارگذاری مشخصه data-src را به همان روشی که مشخصه src (یا srcset) را می‌خواند نمی‌خواند، مرجع تصویر زودتر کشف نمی‌شود. بدتر اینکه بار شدن تصویر تا بعداز بارگیری، کامپایل، و اجرای جاوا اسکریپت بارکننده کُند به‌تأخیر می‌افتد.

نمودار آبشاری شبکه WebPageTest که نشان می‌دهد چگونه تصویری با بارگذاری کُند که درطول راه‌اندازی در نمای هدف قرار دارد، لزوماً به‌تأخیر می‌افتد زیرا اسکنر پیش‌بارگذاری مرورگر نمی‌تواند منبع تصویر را پیدا کند و تنها زمانی بار می‌شود که جاوا اسکریپت موردنیاز برای عملکرد بارگذاری کُند بار شود. تصویر خیلی دیرتر از زمانی که باید پیدا می‌شود.
شکل ۸: نمودار آبشاری شبکه WebPageTest از یک صفحه وب که در Chrome روی دستگاه همراه ازطریق اتصال 3G شبیه‌سازی‌شده اجرا می‌شود. منبع تصویر به‌طور غیرضروری بارگذاری کُند می‌شود، هرچند درطول راه‌اندازی در نمای دید قابل‌مشاهده است. این کار اسکنر پیش‌بارگیری را ازکار می‌اندازد و باعث تأخیر غیرضروری می‌شود.

بسته به اندازه تصویر (که ممکن است به اندازه ناحیه نمایش بستگی داشته باشد)، ممکن است عنصر نامزدی برای بزرگ‌ترین نقاشی دارای محتوا (LCP) باشد. وقتی اسکنر پیش‌بارگیری نمی‌تواند منبع تصویر را پیش‌از موعد به‌صورت فرضی واکشی کند (احتمالاً در نقطه‌ای که برگه(های) سبک نگارش صفحه پرداز را مسدود می‌کند)، «بزرگ‌ترین نقاشی دارای محتوا» دچار مشکل می‌شود.

راه حل این است که نشانه‌گذاری تصویر را تغییر دهید:

<img src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">

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

نمودار آبشاری شبکه WebPageTest که سناریوی بارگیری تصویر در نمای دید را درطول راه‌اندازی نشان می‌دهد. تصویر به‌صورت کُند بار نمی‌شود، یعنی برای بار شدن به دستورگان وابسته نیست، بنابراین اسکنر پیش‌بارگیری می‌تواند آن را زودتر پیدا کند.
شکل ۹: نمودار آبشاری شبکه WebPageTest از یک صفحه وب که در Chrome در دستگاه همراه ازطریق اتصال 3G شبیه‌سازی‌شده اجرا می‌شود. اسکنر پیش‌بارگذاری منبع تصویر را قبل‌از شروع بار شدن CSS و جاوا اسکریپت پیدا می‌کند، که باعث می‌شود مرورگر در بار کردن آن پیشی بگیرد.

نتیجه این مثال ساده‌شده، بهبود ۱۰۰ میلی‌ثانیه‌ای در LCP در اتصال کند است. شاید این بهبود بزرگی به‌نظر نرسد، اما وقتی درنظر بگیرید که راه‌حل یک اصلاح نشانه‌گذاری سریع است و اکثر صفحه‌های وب پیچیده‌تر از این مجموعه مثال‌ها هستند، متوجه اهمیت آن می‌شوید. این یعنی نامزدهای LCP ممکن است مجبور شوند برای پهنای باند با بسیاری از منابع دیگر رقابت کنند، بنابراین بهینه‌سازی‌هایی مانند این به‌طور فزاینده‌ای اهمیت پیدا می‌کنند.

تصاویر پس‌زمینه CSS

به‌یاد داشته باشید که اسکنر پیش‌بارگذاری مرورگر نشانه‌گذاری را اسکن می‌کند. انواع دیگر منابع را اسکن نمی‌کند، مانند CSS که ممکن است شامل واکشی برای تصاویر ارجاع‌شده توسط background-image ویژگی باشد.

مرورگرها CSS را مانند HTML در مدل شیء خودش پردازش می‌کنند که به آن CSSOM می‌گویند. اگر منابع خارجی هنگام ساخت CSSOM کشف شوند، آن منابع در زمان کشف درخواست می‌شوند و نه توسط اسکنر پیش‌بارگذاری.

فرض کنید نامزد LCP صفحه شما عنصری با ویژگی CSS background-image است. هنگام بار شدن منابع، موارد زیر اتفاق می‌افتد:

نمودار آبشاری شبکه WebPageTest که صفحه‌ای را با نامزد LCP بارشده از CSS بااستفاده از ویژگی background-image نشان می‌دهد. چون تصویر نامزد «بزرگ‌ترین نقاشی دارای محتوا» در نوع منبعی است که اسکنر پیش‌بارگیری مرورگر نمی‌تواند آن را بررسی کند، بار کردن منبع تا زمانی که CSS بارگیری و پردازش نشود به‌تأخیر می‌افتد و این امر زمان نقاشی نامزد «بزرگ‌ترین نقاشی دارای محتوا» را به‌تأخیر می‌اندازد.
شکل ۱۰: نمودار آبشاری شبکه WebPageTest از یک صفحه وب که در Chrome در دستگاه همراه ازطریق اتصال 3G شبیه‌سازی‌شده اجرا می‌شود. نامزد LCP صفحه عنصری با ویژگی CSS background-image است (ردیف ۳). تصویری که درخواست می‌کند تا زمانی که تجزیه‌کننده CSS آن را پیدا نکند، واکشی نمی‌شود.

در این مورد، اسکنر پیش‌بارگذاری چندان شکست نمی‌خورد، بلکه بیشتر درگیر نمی‌شود. بااین‌حال، اگر یک نامزد LCP در صفحه از ویژگی CSS background-image باشد، باید آن تصویر را پیش‌بارگیری کنید:

<!-- Make sure this is in the <head> below any
     stylesheets, so as not to block them from loading -->
<link rel="preload" as="image" href="lcp-image.jpg">

این اشاره rel=preload کوچک است، اما به مرورگر کمک می‌کند تصویر را زودتر از آنچه درغیراین‌صورت انجام می‌داد، کشف کند:

نمودار آبشاری شبکه WebPageTest که نشان می‌دهد تصویر پس‌زمینه CSS (که نامزد LCP است) به‌دلیل استفاده از اشاره rel=preload بسیار زودتر بار می‌شود. زمان LCP تقریباً ۲۵۰ میلی‌ثانیه بهبود می‌یابد.
شکل ۱۱: نمودار آبشاری شبکه WebPageTest از یک صفحه وب که در Chrome در دستگاه همراه ازطریق اتصال 3G شبیه‌سازی‌شده اجرا می‌شود. نامزد LCP صفحه عنصری با ویژگی CSS background-image است (ردیف ۳). نکته rel=preload به مرورگر کمک می‌کند تا تصویر را حدود ۲۵۰ میلی‌ثانیه زودتر از زمانی که نکته وجود ندارد پیدا کند.

با راهنمایی rel=preload، نامزد LCP زودتر کشف می‌شود و زمان LCP کاهش می‌یابد. اگرچه این نکته به رفع این مشکل کمک می‌کند، اما گزینه بهتر ممکن است ارزیابی این باشد که آیا تصویر نامزد LCP شما باید از CSS بارگیری شود یا نه. با برچسب <img>، کنترل بیشتری بر بار کردن تصویری خواهید داشت که برای نمای دید مناسب است و درعین‌حال به اسکنر پیش‌بارگذاری اجازه می‌دهد آن را پیدا کند.

درون‌خطی کردن منابع بسیار زیاد

درون‌خطی کردن روشی است که منبعی را درون HTML قرار می‌دهد. می‌توانید برگه سبک نگارش را در عناصر <style>، اسکریپت‌ها را در عناصر <script>، و تقریباً هر منبع دیگری را بااستفاده از کدبندی ۶۴پایه‌ای به‌صورت درون‌خطی قرار دهید.

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

  • اگر HTML خود را در حافظه نهان ذخیره نمی‌کنید (و اگر پاسخ HTML پویا باشد، نمی‌توانید این کار را انجام دهید)، منابع درون‌خطی هرگز در حافظه نهان ذخیره نمی‌شوند. این امر بر عملکرد تأثیر می‌گذارد زیرا منابع درون‌خطی قابل‌استفاده مجدد نیستند.
  • حتی اگر بتوانید HTML را در حافظه پنهان ذخیره کنید، منابع درون‌خطی بین اسناد هم‌رسانی نمی‌شوند. این کار کارایی ذخیره‌سازی موقت را درمقایسه با فایل‌های خارجی که می‌توانند در سراسر یک مبدأ ذخیره موقت و مجدداً استفاده شوند کاهش می‌دهد.
  • اگر بیش‌ازحد درون‌خطی کنید، اسکنر پیش‌بارگیری را در کشف منابع بعدی در سند به‌تأخیر می‌اندازید، زیرا بارگیری آن محتوای درون‌خطی اضافی بیشتر طول می‌کشد.

این صفحه را به‌عنوان نمونه درنظر بگیرید. در شرایط خاصی، نامزد LCP تصویر بالای صفحه است و CSS در فایل جداگانه‌ای است که توسط عنصر <link> بار می‌شود. این صفحه همچنین از چهار قلم وب استفاده می‌کند که به‌عنوان فایل‌های جداگانه از منبع CSS درخواست می‌شوند.

نمودار آبشاری شبکه WebPageTest از صفحه‌ای با فایل CSS خارجی که چهار قلم در آن ارجاع داده شده است. تصویر نامزد LCP در زمان مناسب توسط اسکنر پیش‌بارگیری شناسایی می‌شود.
شکل ۱۲: نمودار آبشاری شبکه WebPageTest از یک صفحه وب که در Chrome در دستگاه همراه ازطریق اتصال 3G شبیه‌سازی‌شده اجرا می‌شود. نامزد «بزرگ‌ترین نقاشی دارای محتوا» صفحه تصویری است که از عنصر <img> بار شده است، اما توسط اسکنر پیش‌بارگذاری کشف شده است زیرا CSS و قلم‌های موردنیاز برای بار کردن صفحه در منابع جداگانه‌ای قرار دارند که باعث تأخیر در کار اسکنر پیش‌بارگذاری نمی‌شود.

اکنون چه اتفاقی می‌افتد اگر CSS و همه قلم‌ها به‌عنوان منابع base64 درون‌خطی شوند؟

نمودار آبشاری شبکه WebPageTest از صفحه با فایل CSS خارجی با چهار قلم ارجاع‌شده در آن. اسکنر پیش‌بارگذاری با تأخیر قابل‌توجهی تصویر LCP را شناسایی می‌کند .
شکل ۱۳: نمودار آبشاری شبکه WebPageTest از یک صفحه وب که در Chrome در دستگاه همراه ازطریق اتصال 3G شبیه‌سازی‌شده اجرا می‌شود. نامزد «بزرگ‌ترین نقاشی دارای محتوا» صفحه تصویری است که از عنصر <img> بار شده است، اما درون‌خطی کردن CSS و چهار منبع قلم آن در `` باعث می‌شود اسکنر پیش‌بارگذاری تا زمانی که آن منابع کاملاً بارگیری نشده‌اند تصویر را پیدا نکند.

تأثیر درون‌خطی کردن در این مثال پیامدهای منفی برای LCP دارد—و به‌طور کلی برای عملکرد. نسخه صفحه‌ای که هیچ‌چیز را درون‌خطی نمی‌کند، تصویر LCP را در حدود ۳٫۵ ثانیه رنگ‌آمیزی می‌کند. صفحه‌ای که همه چیز را درون‌خطی می‌کند، تصویر LCP را تا کمی بیش از ۷ ثانیه رنگ‌آمیزی نمی‌کند.

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

Could a preload improve things here? حتماً. می‌توانید تصویر LCP را پیش‌بارگیری کنید و زمان LCP را کاهش دهید، اما حجیم کردن HTML بالقوه غیرقابل‌ذخیره‌سازی در حافظه نهان با منابع درون‌خطی پیامدهای منفی دیگری بر عملکرد دارد. اولین نقاشی دارای محتوا (FCP) نیز تحت‌تأثیر این الگو قرار می‌گیرد. در نسخه‌ای از صفحه که هیچ‌چیز درون‌خطی نیست، FCP تقریباً ۲٫۷ ثانیه است. در نسخه‌ای که همه چیز درون‌خطی است، FCP تقریباً ۵٫۸ ثانیه است.

هنگام درون‌خطی کردن موارد در HTML، به‌ویژه منابع کدبندی‌شده با base64، بسیار مراقب باشید. به‌طور کلی توصیه نمی‌شود، به‌جز برای منابع بسیار کوچک. تا حد امکان کمتر از کد درون‌خطی استفاده کنید، زیرا استفاده بیش‌ازحد از کد درون‌خطی بازی با آتش است.

پرداز زدن نشانه‌گذاری با جاوا اسکریپت سمت کارخواه

شکی در این نیست: جاوا اسکریپت قطعاً بر سرعت صفحه تأثیر می‌گذارد. نه تنها توسعه‌دهندگان برای ارائه تعامل به آن وابسته هستند، بلکه تمایلی نیز به تکیه بر آن برای ارائه خود محتوا وجود داشته است. این کار از برخی جهات به تجربه بهتر توسعه‌دهنده منجر می‌شود؛ اما مزایای توسعه‌دهندگان همیشه به مزایای کاربران تبدیل نمی‌شود.

یک الگو که می‌تواند اسکنر پیش‌بارگذاری را شکست دهد، رندر کردن نشانه‌گذاری با جاوا اسکریپت سمت کارخواه است:

آبشار شبکه WebPageTest که صفحه‌ای ساده با تصاویر و نوشتار را نشان می‌دهد که کاملاً در سمت کارخواه در جاوا اسکریپت پرداز شده است. چون نشانه‌گذاری در جاوا اسکریپت قرار دارد، اسکنر پیش‌بارگیری نمی‌تواند هیچ‌کدام از منابع را شناسایی کند. همه منابع به‌دلیل شبکه اضافی و زمان پردازشی که چارچوب‌های جاوا اسکریپت نیاز دارند، با تأخیر بیشتری مواجه می‌شوند.
شکل ۱۴: نمودار آبشاری شبکه WebPageTest از صفحه وب ارائه‌شده توسط کارخواه که در Chrome در دستگاه همراه ازطریق اتصال 3G شبیه‌سازی‌شده اجرا می‌شود. چون محتوا در جاوا اسکریپت قرار دارد و برای ارائه به چارچوب متکی است، منبع تصویر در نشانه‌گذاری ارائه‌شده توسط کارخواه از اسکنر پیش‌بارگیری پنهان است. تجربه معادل ارائه‌شده توسط سرور در شکل ۹ نشان داده شده است.

وقتی محموله‌های نشانه‌گذاری در جاوا اسکریپت در مرورگر قرار دارند و کاملاً توسط آن ارائه می‌شوند، هر منبعی در آن نشانه‌گذاری عملاً برای اسکنر پیش‌بارگیری نامرئی است. این کار باعث تأخیر در کشف منابع مهم می‌شود که قطعاً بر LCP تأثیر می‌گذارد. در این مثال‌ها، درخواست تصویر LCP درمقایسه با تجربه معادل ارائه‌شده توسط سرور که برای نمایش به جاوا اسکریپت نیاز ندارد، به‌طور قابل‌توجهی به‌تأخیر می‌افتد.

این موضوع کمی از تمرکز این مقاله منحرف می‌شود، اما تأثیرات نشانه‌گذاری رندرینگ در کارخواه بسیار فراتر از شکست دادن اسکنر پیش‌بارگیری است. برای مثال، معرفی جاوا اسکریپت برای تقویت تجربه‌ای که به آن نیاز ندارد، زمان پردازش غیرضروری را معرفی می‌کند که می‌تواند بر تعامل تا ترسیم بعدی (INP) تأثیر بگذارد. پرداخت مقدار بسیار زیادی نشان‌گذاری در کارخواه درمقایسه با ارسال همان مقدار نشان‌گذاری توسط سرور، احتمال بیشتری دارد که تکالیف طولانی ایجاد کند. دلیل این امر (صرف‌نظر از پردازش اضافی که جاوا اسکریپت شامل می‌شود) این است که مرورگرها نشانه‌گذاری را از سرور جاری‌سازی می‌کنند و رندر کردن را به‌گونه‌ای تقسیم می‌کنند که تمایل دارد کارهای طولانی را محدود کند. ازسوی دیگر، نشانه‌گذاری پردازش‌شده در سمت کارخواه به‌عنوان یک کار یکپارچه و یک‌تکه مدیریت می‌شود که ممکن است بر INP صفحه تأثیر بگذارد.

راه‌حل این سناریو به پاسخ این سؤال بستگی دارد: آیا دلیلی وجود دارد که نشانه‌گذاری صفحه شما نمی‌تواند توسط سرور ارائه شود و باید در سمت کارخواه پرداز شود؟ اگر پاسخ به این سؤال «نه» است، درصورت امکان باید از نشانه‌گذاری تولیدشده به‌صورت ایستا یا پردازش سمت سرور (SSR) استفاده شود، زیرا این کار به اسکنر پیش‌بارگیری کمک می‌کند تا منابع مهم را زودتر از موعد کشف و به‌طور فرصت‌طلبانه واکشی کند.

اگر صفحه شما برای افزودن عملکرد به برخی‌از بخش‌های نشانه‌گذاری صفحه به «جاوا اسکریپت» نیاز دارد، همچنان می‌توانید این کار را با SSR انجام دهید، چه با «جاوا اسکریپت» خالص یا هیدراتاسیون تا از مزایای هر دو روش بهره‌مند شوید.

به اسکنر پیش‌بارگیری کمک کنید تا به شما کمک کند

اسکنر پیش‌بارگذاری یک بهینه‌سازی بسیار مؤثر مرورگر است که به بارگیری سریع‌تر صفحه‌ها درطول راه‌اندازی کمک می‌کند. با اجتناب از الگوهایی که توانایی آن را برای کشف منابع مهم پیش‌از موعد ازبین می‌برند، نه‌تنها توسعه را برای خود ساده‌تر می‌کنید، بلکه تجربه‌های کاربری بهتری ایجاد می‌کنید که نتایج بهتری را در بسیاری از سنجه‌ها، ازجمله برخی حیاتی‌های وب، ارائه می‌دهد.

به‌عنوان خلاصه، موارد زیر را از این پست به‌خاطر بسپارید:

  • اسکنر پیش‌بارگیری مرورگر یک تجزیه‌کننده HTML ثانویه است که اگر تجزیه‌کننده اصلی مسدود شده باشد، جلوتر از آن اسکن می‌کند تا منابعی را که می‌تواند زودتر واکشی کند به‌طور فرصت‌طلبانه کشف کند.
  • منابعی که در نشانه‌گذاری ارائه‌شده توسط سرور در درخواست پیمایش اولیه وجود ندارند، نمی‌توانند توسط اسکنر پیش‌بارگذاری کشف شوند. روش‌هایی که اسکنر پیش‌بارگذاری می‌تواند شکست بخورد ممکن است شامل (اما نه محدود به) موارد زیر باشد:
    • تزریق منابع به DOM با جاوا اسکریپت، خواه اسکریپت، تصویر، برگه سبک نگارش، یا هر چیز دیگری باشد که بهتر است در بار داده نشانه‌گذاری اولیه از سرور قرار گیرد.
    • بار کردن کُند تصاویر یا iframeهای بالای خط تا بااستفاده از راهکار جاوا اسکریپت.
    • پرداخت نشانه‌گذاری در کارخواه که ممکن است حاوی ارجاع به زیرمنابع سند بااستفاده از جاوا اسکریپت باشد.
  • اسکنر پیش‌بارگذاری فقط HTML را اسکن می‌کند. محتوای منابع دیگر (به‌ویژه CSS) را که ممکن است شامل ارجاع به دارایی‌های مهم، ازجمله نامزدهای LCP باشد، بررسی نمی‌کند.

اگر به هر دلیلی نمی‌توانید از الگویی که بر توانایی اسکنر پیش‌بارگذاری برای سرعت بخشیدن به عملکرد بارگیری تأثیر منفی می‌گذارد اجتناب کنید، راهنمایی منبع rel=preload را درنظر بگیرید. اگر از rel=preload استفاده می‌کنید، در ابزارهای آزمایشگاهی آزمایش کنید تا مطمئن شوید که جلوه دلخواه را به شما می‌دهد. درنهایت، منابع زیادی را پیش‌بار نکنید، زیرا وقتی همه چیز را اولویت‌بندی می‌کنید، هیچ چیز اولویت‌بندی نخواهد شد.

منابع