گنجاندن منابع در چارچوب های جاوا اسکریپت

بهبود بزرگترین رنگ محتوایی در اکوسیستم جاوا اسکریپت.

به عنوان بخشی از پروژه Aurora ، Google با چارچوب های وب محبوب کار می کند تا اطمینان حاصل کند که آنها مطابق Core Web Vitals عملکرد خوبی دارند. Angular و Next.js قبلاً فونت‌های داخلی را وارد کرده‌اند که در قسمت اول این مقاله توضیح داده شده است. دومین بهینه‌سازی که پوشش خواهیم داد، CSS inlining حیاتی است که اکنون به‌طور پیش‌فرض در Angular CLI فعال شده است و در Nuxt.js در حال انجام است.

خط بندی فونت

پس از تجزیه و تحلیل صدها برنامه، تیم Aurora دریافت که توسعه دهندگان اغلب فونت ها را با ارجاع به آنها در عنصر <head> در index.html در برنامه های خود قرار می دهند. در اینجا نمونه‌ای از نحوه ظاهر آن هنگام اضافه کردن نمادهای مواد آورده شده است:

<!doctype html>
<html lang="en">
<head>
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  ...
</html>

با وجود اینکه این الگو کاملاً معتبر و کاربردی است، رندر برنامه را مسدود می کند و یک درخواست اضافی را معرفی می کند. برای درک بهتر آنچه در جریان است، به کد منبع شیوه نامه که در HTML بالا اشاره شده است، نگاهی بیندازید:

/* fallback */
@font-face {
  font-family: 'Material Icons';
  font-style: normal;
  font-weight: 400;
  src: url(https://fonts.gstatic.com/font.woff2) format('woff2');
}

.material-icons {
  /*...*/
}

توجه کنید که چگونه تعریف font-face به یک فایل خارجی میزبانی شده در fonts.gstatic.com ارجاع می دهد. هنگام بارگیری برنامه، مرورگر ابتدا باید استایل شیت اصلی را که در head به آن اشاره شده دانلود کند.

تصویری که نشان می‌دهد چگونه وب‌سایت باید از سرور درخواست کند و شیوه نامه خارجی را دانلود کند
ابتدا وب سایت شیوه نامه فونت را بارگیری می کند.

در مرحله بعد، مرورگر فایل woff2 را دانلود می کند، سپس در نهایت، می تواند برنامه را رندر کند.

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

یک فرصت برای بهینه سازی این است که شیوه نامه اولیه را در زمان ساخت دانلود کنید و آن را در index.html درج کنید. با این کار یک سفر رفت و برگشت کامل به CDN در زمان اجرا حذف می شود و زمان مسدود شدن را کاهش می دهد.

هنگام ساخت برنامه، درخواستی به CDN ارسال می شود، این شیوه نامه را واکشی می کند و آن را در فایل HTML خط می دهد و یک <link rel=preconnect> به دامنه اضافه می کند. با استفاده از این تکنیک، به نتیجه زیر می رسیم:

<!doctype html>
<html lang="en">
<head>
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin >
  <style type="text/css">
  @font-face{font-family:'Material Icons';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/font.woff2) format('woff2');}.material-icons{/*...*/}</style>
  ...
</html>

خط‌بندی فونت اکنون در Next.js و Angular در دسترس است

هنگامی که توسعه دهندگان فریم ورک بهینه سازی را در ابزار زیربنایی پیاده سازی می کنند، آن را برای برنامه های موجود و جدید آسان تر می کنند تا آن را فعال کنند و بهبود را برای کل اکوسیستم به ارمغان می آورند.

این بهبود به طور پیش فرض از Next.js v10.2 و Angular v11 فعال شده است. هر دو از فونت های گوگل و ادوبی پشتیبانی می کنند. Angular انتظار دارد نسخه دوم را در نسخه 12.2 معرفی کند.

می‌توانید اجرای inlining فونت را در Next.js در GitHub بیابید و ویدیوی توضیح این بهینه‌سازی را در زمینه Angular ببینید.

درون‌سازی CSS حیاتی

یکی دیگر از پیشرفت‌ها شامل بهبود معیارهای First Contentful Paint (FCP) و Largest Contentful Paint (LCP) با استفاده از CSS حیاتی است. CSS حیاتی یک صفحه شامل تمام سبک های مورد استفاده در رندر اولیه آن است. برای کسب اطلاعات بیشتر در مورد موضوع، Defer non-critical CSS را بررسی کنید.

ما مشاهده کردیم که بسیاری از برنامه‌ها سبک‌ها را به صورت همزمان بارگیری می‌کنند، که رندر برنامه را مسدود می‌کند. یک راه حل سریع بارگذاری سبک ها به صورت ناهمزمان است. به‌جای بارگیری اسکریپت‌ها با media="all" ، مقدار مشخصه media را روی print تنظیم کنید و پس از اتمام بارگیری، مقدار ویژگی را با all جایگزین کنید:

<link rel="stylesheet" href="..." media="print" onload="this.media='all'">

با این حال، این عمل می‌تواند باعث سوسو زدن محتوای بدون سبک شود.

به نظر می رسد که صفحه با بارگیری سبک ها سوسو می زند.

ویدئوی بالا رندر یک صفحه را نشان می دهد که سبک های آن را به صورت ناهمزمان بارگذاری می کند. سوسو زدن به این دلیل اتفاق می‌افتد که مرورگر ابتدا شروع به دانلود سبک‌ها می‌کند، سپس HTML را که در ادامه می‌آید ارائه می‌کند. هنگامی که مرورگر سبک‌ها را دانلود کرد، رویداد onload عنصر پیوند را فعال می‌کند، ویژگی media را برای all به‌روزرسانی می‌کند و سبک‌ها را در DOM اعمال می‌کند.

در طول زمان بین رندر HTML و اعمال سبک ها، صفحه تا حدی سبک نشده است. وقتی مرورگر از سبک‌ها استفاده می‌کند، شاهد سوسو زدن هستیم که تجربه کاربری بدی است و منجر به رگرسیون در تغییر چیدمان تجمعی (CLS) می‌شود.

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

بیایید به یک مثال نگاه کنیم:

نکن
<head>
   <link rel="stylesheet" href="/styles.css" media="print" onload="this.media='all'">
</head>
<body>
  <section>
    <button class="primary"></button>
  </section>
</body>
/* styles.css */
section button.primary {
  /* ... */
}
.list {
  /* ... */
}

مثال قبل از خط کشی

در مثال بالا، مخلوقات محتوای styles.css را می‌خوانند و تجزیه می‌کنند، پس از آن دو انتخابگر را با HTML مطابقت می‌دهند و متوجه می‌شوند که ما section button.primary استفاده می‌کنیم. در نهایت مخلوقات استایل های مربوطه را در <head> صفحه درج می کنند و در نتیجه:

انجام دادن
<head>
  <link rel="stylesheet" href="/styles.css" media="print" onload="this.media='all'">
  <style>
  section button.primary {
    /* ... */
  }
  </style>
</head>
<body>
  <section>
    <button class="primary"></button>
  </section>
</body>

مثال بعد از خط کشی

پس از وارد کردن CSS حیاتی در HTML، متوجه خواهید شد که سوسو زدن صفحه از بین رفته است:

صفحه در حال بارگذاری پس از CSS درون خطی.

Critical CSS inlining اکنون در Angular در دسترس است و به طور پیش فرض در نسخه 12 فعال است. اگر از نسخه 11 استفاده می کنید، با تنظیم ویژگی inlineCritical روی true در angular.json ، آن را روشن کنید. برای انتخاب این ویژگی در Next.js experimental: { optimizeCss: true } به next.config.js خود اضافه کنید.

نتیجه گیری

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

درباره بهبودها بیشتر بدانید . می‌توانید فهرست جامعی از کارهای بهینه‌سازی که برای Core Web Vitals انجام داده‌ایم را در پست معرفی Aurora بیابید.