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

بهبود Performance فرانت‌اند با FOIT، FOUT و CLS

گوگل مجموعه‌ای از شاخص‌ها رو برای اندازه گیری کیفیت UX/UI، سرعت بارگذاری، میزان ثبات بصری و ... رو تحت عنوان Core Web Vitals معرفی کرده که یکی از این شاخص‌های CLS هست، مخفف cumulative layout shift.

این شاخص میزان پایداری و ثبات صفحه رو نشون میده و می‌تونید در پنجره performance در developer tools مرورگر chrome اون رو بررسی کنید. یکی از عاملی که روی اون تاثیر جدی میذاره بحث لود شدن فونت‌ها هست که در این مطلب می‌خوایم با هم اون رو بشناسیم و راهکارهای بهبودش رو درک کنیم.

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

شاخص CLS از دو پارامتر تشکیل شده و عدد حاصل از این دو در هم ضرب میشه و مقدار CLS رو میسازه. در پارامتر impact fraction (IF) این بررسی میشه که چقدر از سطح viewport (پنجره در حال نمایش به کاربر) تحت تاثیر این تغییرات غیرمنتظره قرار گرفته و در پارامتر بعدی یعنی distance fraction (DF) هم این اندازه گیری میشه که فاصله اون تغییرات رخ داده تا viewport چقدر هست. طبیعتا هر چه سطحی کمتری از صفحه درگیری این تغییرات بشه و هر چه از محل در حال نمایش به کاربر دورتر باشه تاثیر کمتری بر تجربه کاربر میذاره پس CLS بهتری خواهیم داشت.

CLS (Cumulative Layout Shift)
CLS (Cumulative Layout Shift)

CLS = IF * DF

اگر عدد CLS به دست امده از 0.1 کمتر بود ما عالی عمل کردیم و اگر از 0.25 بیشتر بود یعنی با یک افتضاح رو به رو هستیم و طبیعتا عدد بین این دو نیاز به تلاش برای بهبود داره و این مقدار رو در تب performance در developer tools مرورگر chrome برای صفحه جاری می‌تونید ببنید.

یکی از تلاش‌هایی که برای بهبود شاخص CLS میشه کرد، optimise کردن حجم و نحوه و سرعت لود ‌اونهاست. در طی لود شدن فونت‌ها بسته به این که ما font-display رو چطور تعریف کرده باشم FOIT (یهو ظاهرا شدن متن‌ها) و FOUT (یهو استایل پیدا کردن متن‌ها) می‌تونه رخ بده و روی شاخص CLS تاثیر بذاره.

Flash Of Unstyled Tex & Flash Of Invisible Text
Flash Of Unstyled Tex & Flash Of Invisible Text


وقتی یک فونت رو در کل یا بخش از صفحه استفاده می‌کنیم مرورگر در طی پردازش و painting وقتی به اون المنت میرسه ابتدا تلاش می‌کنه تا به فایل فونت دسترسی پیدا کنه. اگر اون فونت قبلا لود و کش شده باشه یا فونت پیش فرض سیستم استفاده شده باشه در همین مرحله اغلب متن‌ها با فونت مورد نظر render میشن. اما وقتی ما از یک فونت خارجی استفاده کرده باشیم قضیه کمی پیچیده‌تر میشه و به طول کلی این پروسه سه بخش block, swap و failure می‌تونه داشته باشه که البته بسته به این که font-display چی تعریف شده ممکن هست بعضی از این‌ها رو نداشته باشیم و تغییراتی هم این فاز‌ها داشته باشم.

حواستون باشه این ۳ حالتی که پایین توضیح دادم مقدایر font-display نیست بلکه چرخه‌هایی مفهومی هستن و در ظاهر با مقادیر font-display شباهت دارن ولی در تعریف می‌تونن متفاوت باشن!
  • ابتدا مرحله block شروع میشه. در این حالت یک فونت پیش فرض نامرئی به جایگزین فونت خارجی استفاده شده استفاده میشه و اصطلاحا نمایش متن بلاک و مخفی میشه تا نهایتا فونت دانلود و پردازش و طی مرحله swap با این فونت نامرئی جا‌به‌جا بشه. در طی این تعویض فونت نامرئی و فونت قابل مشاهده یک فلش صفحه می‌خوره که به اون FOIT میگن که مخفف flash of invisible text هست.
  • مرحله دوم swap هست و همونطور که در ادامه توضیح بالا گفتیم، در این مرحله فونت دانلود شده روی متن اعمال میشه و به نمایش در میاد. البته می‌تونه بسته به شرایط مرحله block وجود نداشته باشه و فونت پیش فرض سیستم تا زمان دریافت فونت خارجی به عنوان جایگزین نمایش داده بشه و هر وقت اون اماده شد جایگزینی اتفاق بیفته که در اون لحظه ما یک FOUT که مخفف flash of unstyled text هست رو تجربه خواهیم کرد (تغییر ناگهانی ظاهر متن‌ها).
  • حالت سومی هم ممکن هست رخ بده! حالتی که دانلود و پردازش فونت به خطا خورده (failure) و امکان swap عملا وجود نداره! البته اینم ممکن هست که مرورگر خودش با توجه به سیستم کاربر و سرعت اینترنتش تشخیص میده که اون رو failure در نظر بگیره یعنی در واقعیت خطایی نخورده ولی مرورگر پیش بینی کرده که می ‌خوره یا دوست داره که بیخیال ماجرا بشه!

هر کدام از مقادیر font-display روی این سه چرخه لود فونت می‌تونه چنین تغییراتی روی ایجاد کنه:

  • مقدار auto (default): این گزینه که پیش فرض هم هست بسته به user-agent و سرعت اینترنت کاربر و یکسری پارامترهای مثل این، خودش اتوماتیک لود فونت رو مدیریت می‌کنه ولی به طور کلی میشه گفت اغلب شبیه مقدار block عمل می‌کنه ولی خب گاهی ممکن هست تصمیم بگیره تا فونت رو لود نکنه!
  • مقدار block: در این حالت ابتدا میاد عملیات بلاک کردن فونت رو انجام میده (از فونت نامرئی استفاده می‌کنه) و تا مدت کوتاهی هم این صبر استراتژیک رو طول ادامه میده (حدود ۳ ثانیه که بسته به مرورگر می‌تونه متفاوت باشه). اگر در طی نامرئی بود فونت دانلود شد که متن‌ها با فونت تعیین شده render و نمایش داده میشن ولی اگر نشد بعد از این زمان فونت پیش فرض جایگزین میشه ولی مرورگر تا وقتی کاربر در همون صفحه بمونه (بی‌نهایت) منتظر میشه تا درخواست دانلود فونت و پردازشش تکمیل بشه و بعد اون رو با فونت پیش فرض در حال نمایش جابه‌جا می‌کنه اگر هم که failure شد فونت پیش فرض باقی می‌مونه!
  • مقدار swap: اگر این مقدار رو برای font-display تعیین کنیم دیگه مرحله block و نامرئی شدن رو نخواهیم داشت و از همون اول فونت پیش فرض سیستم به جایگزین فونت خارجی برای فونت ها استفاده میشه ولی مرورگر تا وقتی کاربر در همون صفحه بمونه (بی‌نهایت) منتظر میشه تا درخواست دانلود فونت و پردازشش تکمیل بشه و بعد اون رو با فونت پیش فرض در حال نمایش جابه‌جا می‌کنه اگر هم که failure شد فونت پیش فرض باقی می‌مونه!
  • مقدار fallback: اگر سه حالت قبل رو ترکیب کنیم و به نفع لود شدن فونت پیش فرض (fallback) همه چیز رو بچینیم میشه یه همچین حالتی. اولا که مثل حالت auto مرورگر روی اون یکسری بررسی‌ها و تصمیمات اتوماتیک می‌گیره و ممکن هست هر طور صلاح میدونه عمل کنه ولی در اغلب موارد اینطوری هست که زمان بسیار کوتاهی، حدود 100ms فونت رو ابتدا block و نامرئی می‌کنه و بعد فونت پیش فرض رو استفاده می‌کنه و بعد هم زمان کمی، حدود ۳ ثانیه صبر می‌کنه تا فونت لود بشه اگر نشد کلا بیخیال swap میشه و با همون فونت پیش فرض تا هر وقت کاربر مرورگر رو باز نگهداره متن‌ها رو نشون میده. در واقع هدفش این هست که یک تلاش خیلی کوتاه و سریع میکنه تا فونت خارجی رو استفاده کنه، شد که شد نشد بیخیالش میشه.
  • مقدار optional: این دیگه از حالت قبلی یعنی fallback هم افراطی‌تر دنبال لود فونت پیش فرض هست. در واقع مثل همون fallback عمل می‌کنه با این فرق که دیگه ۳ ثانیه هم برای swap صبر نمی‌کنه. کلا 100ms وقت میذاره، فونت رو نامرئی می‌کنه و اگر به فونت تونست دست پیدا کنه استفاده‌ش میکنه مگر نه کلا بیخیالش میشه. البته در این حالت شرایط auto کمی سخت‌گیرانه‌تر هم میشه مثلا اگر اینترنت کاربر کند باشه یا اون فونت حتی بخواد از سیستم خود کاربر خونده بشه ولی سنگین باشه ولودش طول بکشه سریع بیخیال اون فونت میشه و failure در نظرش می‌گیره و با پیش فرض کار رو در میاره (به عبارتی میگه چون لودش خیلی سریع نیست پس بیخیال)!


جمع‌بندی FOUT، FOIT و CLS

همونطور که دید در برخی حالت‌ها و شرایط ما می‌تونیم شیف و فلش خوردن صفحه رو به واسطه لود شدن فونت‌ها تجربه کنیم و اگر هدف ما این باشه که CLS رو کاهش بدیم باید تا می تونیم در قدم اول تعداد فونت‌هایی که استفاده می‌کنیم رو کاهش بدیم و ترجیحا از یک یا نهایتا دوتا فونت استفاده کنیم، در قدم بعدی subset‌ و weightهای بلااستفاده رو از فونت که مورد استفاده قرار نمی‌گیرن حذف کنیم تا حجمش کم بشه و در نهایت با راهکارهای سمت سروری مثل کش کردن سرعت دانلود فونت رو افزایش بدیم و در نهایت نه به شکل افراطی بلکه خیلی معقول از انیمیشن‌هایی مثل fade-in در موارد که فلش خورد در لود داریم استفاده کنیم

استفاده از انیمیشن‌هایی که منجر به تغییر سایزهایی ممتد المنت میشن و این باعث میشه تا المنت‌های جانبیشون رو هم تغییر کنن و به نوعی در کل صفحه حرکت ایجاد کنن مخصوصا در لود اولیه جدا خودداری کنید هم در پردازش بد پرفورمنس هستن و هم در تجربه کاربری و بصری و می‌تونن عاملی برای بدتر شدن نرخ CLS باشن.

همچنین بهتره از font-displayهایی که سخت‌گیرانه‌تر عمل می‌کنن مثل fallback استفاده کنید و فونت‌های پیش فرض مناسبی رو تعیین کنید اگر هم که حتما لود فونت خارجی رو حتی با اندکی افزایش CLS ترجیح دادید بهتره از swap به جای block استفاده کنید.

اگر نکته‌ای جا مونده اون رو در کامنت‌ها اضافه کن.

محمد ابراهیمی اول ـــــــ اردیبهشت ۱۴۰۴

frontend
۴
۳
محمد ابراهیمی اول
محمد ابراهیمی اول
یاد می‌گیرم، تجربه می‌کنم، اشتباه می‌کنم و این چرخه من است تا موفق بشم یا ازش درس بگیرم.
شاید از این پست‌ها خوشتان بیاید