بهینه‌سازی مرحله‌ی Style calculation

تغییر دادن DOM از طریق حذف عناصر، تغییر attributeهایشان، کلاس‌هایشان یا توسّط انیمیشن، همه و همه باعث می‌شوند تا مرورگر دوباره استایل‌ها را بررسی کند و ببیند به چه عناصری باید چه استایل‌هایی اعمال شود و خیلی وقت‌ها چیدمان صفحه یا قسمتی از آن را درست کند. به این فرآیند «محاسبه‌ی استایل‌های نهایی» یا «computed styles calculation» گفته می‌شود.

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

در مرحله‌ی دوم این فرآیند، مرورگر نگاه می‌کند که تک تک دستورات css با کدام انتخابگرها تطابق پیدا کرده‌اند، اولویّت استایل‌ها چگونه است و هر عنصر در نهایت چه استایل‌هایی خواهد گرفت. در موتور Blink (یعنی موتور رندر مرورگر Chrome و Opera) هزینه‌ی مرحله‌ی اوّل و دوم تقریباً یکسان است.

خلاصه

 

  • پیچیدگی انتخابگرها را کم کنید؛ از یک متدلوژی کلاس‌محور مثل BEM استفاده کنید.
  • تعداد عناصری را که استایل‌هایشان باید پردازش شود کم کنید.

پیچیدگی انتخابگرها را کم کنید

در ساده‌ترین حالت فقط با یک کلاس، عنصری در صفحه را انتخاب می‌کنید:

.title {
    /* استایل‌ها */
}

امّا هرچه پروژه بزرگتر می‌شود، انتخابگرها پیچیده‌تر می‌شوند، مثلاً در نهایت ممکن است انتخابگرهایی مثل این بنویسید:

.box:nth-last-child(-n+1) .title {
    /* استایل‌ها */
}

در این صورت، برای اینکه مرورگر بفهمد این استایل‌ها را باید به کدام عنصرها بدهد می‌پرسد «آیا عنصری با کلاس title داریم که پدرش -n+1 اُمین فرزندِ عنصری با کلاس box باشد؟» پیدا کردن جواب این طور سؤال‌ها ممکن است وقت زیادی بگیرد، که نسبت به انتخابگرهای استفاده شده و مرورگری که کد را اجرا می‌کند این زمان تفاوت دارد. همین عنصر مثال فعلی را می‌شد با دادن یک کلاس جداگانه به این صورت انتخاب کرد:

.final-box-title {
    /* استایل‌ها */
}

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

تعداد عناصری که استایل می‌گیرند را کم کنید

عامل دیگری که معمولاً مهم‌تر هم هست، مقدار کاری است که مرورگر هنگام تغییرات عنصر به صورت خالص انجام می‌دهد.

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

نکته: بر این اساس اگر کلاسِ عنصری مثل body را عوض کنید، باید استایل تمام فرزندان و نسل آن دوباره محاسبه شود. ولی خدا را شکر این اتّفاق نمی‌افتد؛ بعضی از مرورگرها مجموعه‌ی کوچکی از دستورات را منحصراً برای هر عنصر نگهداری می‌کنند، که اگر تغییر کرد، موجب محاسبه‌ی دوباره‌ی استایل‌های همان عنصر بشود. این یعنی بر اساس این‌که چه چیزی تغییر کرده است و عنصر مورد نظر در چه مکانی در درخت DOM قرار دارد ممکن است استایل‌های آن عنصر دوباره محاسبه بشود یا نشود.

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

نکته: اگر با Web Componentها کار کرده باشید، در آن‌جا قضیه کمی فرق می‌کند. زیرا به صورت پیش‌فرض استایل‌ها از مرز Shadow DOM عبور نمی‌کنند، و به یک کامپوننت خاص محدود می‌شوند، و کلّ درخت DOM برای تغییرات استایل بررسی نمی‌شود. ولی به صورت کلّی همان مفهوم این‌جا هم هست: درخت‌های DOM کوچکتر با دستورات ساده‌تر، سریع‌تر از درخت‌های DOM بزرگتر یا دارای دستورات پیچیده محاسبه خواهند شد.

هزینه‌ی محاسبه‌ی استایل‌های خود را بسنجید

ساده ترین و بهترین روش برای سنجیدن style calculation استفاده از پنل Performance در DevTools مرورگر کروم است. برای شروع کلید F12 را فشار دهید تا DevTools باز شود. سپس به سربرگ Performance بروید و روی دکمه‌ی ضبط کلیک کنید و با سایت‌تان کار کنید. وقتی ضبط را متوقّف کنید با تصویری مثل زیر مواجه می‌شوید:

نتایج ضبط Performance

در این تصویر روی قطعاتی که به رنگ بنفش هستند کلیک کنید تا جزئیات بیشتر آن را ببینید.

اطّلاعات مربوط به محاسبه‌ی استایل

در این تصویری که الآن می‌بینید با یک style calculation طولانی که ۱۸ میلی‌ثانیه طول کشیده است مواجه هستیم. اگر این محاسبه در حین اجرای انیمیشنی مثل اسکرول اتّفاق افتاده باشد باعث قفل شدن اسکرول و jank قابل توجّهی شده است.

در قسمت Call Site Stack می‌توانید ببینید کدام خط از کد جاوااسکریپت شما مسئول اجرای این style calculation است. علاوه بر آن در قسمت Elements affected می‌توانید ببینید چه تعداد عنصر تحت تأثیر آن قرار گرفته اند (که در این مثال حدود ۴۰۰ عنصر است). از طرفی مدّت زمان اجرای این محاسبه را هم می‌بینید. با استفاده از این اطّلاعات می‌توانید دنبال یافتن راهی برای اصلاح کد خود بگردید.

از BEM استفاده کنید

روش‌هایی مثل BEM (Block, Element, Modifier) برای کدنویسی css واقعاً در افزایش سرعت این بخش تأثیر دارند، زیرا در این روش توصیه شده است که هر چیزی فقط یک کلاس داشته باشد، و در جاهایی که نیاز به نوشتن سلسله‌مراتب است به این شکل عمل می‌شود:

.list { }
.list__list-item { }

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

.list__list-item--last-child {}

اگر دنبال راهی برای سازماندهی css می‌گردید، BEM واقعاً نقطه‌ی شروع خوبی برای این کار است، هم از نظر ساختار کد، و هم از این نظر که وقتی دنبال استایل‌هایتان می‌گردید راحت می‌توانید آن‌ها را پیدا کنید.

برای یادگیری کامل روش BEM برای نام‌گذاری کلاس‌های CSS به لینک زیر مراجعه کنید:
معرفی روش BEM برای نامگذاری کلاس‎ها

اگر از روش BEM خوشتان نمی‌آید، روش‌های دیگری نزدیک به آن هم وجود دارد. ولی از لحاظ سرعت و performance باید ارزیابی شوند.

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *