وقتی حرف i تو یه فایل فونت دیگهست و INP سایت بالا میره
خلاصهٔ کاملتر
نویسنده داشت یه WordPress multisite چندزبانه رو بررسی میکرد که دید LCP و INP بالا رفتن و Search Console یه سری صفحهی موبایل رو بالای ۲۰۰ میلیثانیه INP نشون میده. INP (یعنی مدت زمانی که طول میکشه صفحه بعد از کلیک یا تپ واکنش نشون بده) سه بخش داره: تأخیر ورودی، اجرای event handlerها و presentation delay. اینجا جاوااسکریپت تقریباً کاری نمیکرد و زمان توی بخش آخر، یعنی چیدن متن (text layout)، میرفت.
سایت یه فونت بزرگ CJK داره که با ابزار متنباز cn-font-split به چندصد فایل کوچیک تقسیم شده. هر فایل یه قانون @font-face با یه unicode-range داره، یعنی لیست حروفی که اون فایل پوشش میده، تا مرورگر فقط چیزی رو که لازمه دانلود کنه. مشکل این بود که حروف پایهی انگلیسی تو چند فایل پخش شده بودن.
نویسنده همین رو با cn-font-split 7.4.3 و فونت Noto Sans SC تکرار کرده: ۲۹۳ فایل ساخته شد و ۹۵ حرف پایهی لاتین (U+20 تا U+7E) تو دو فایل افتادن. فایل کوچیکتر ۱۱ کاراکتر داره، از جمله M، N، i و j. مثلاً کلمهی injection تو ۹ حرف پنج بار بین فایلها جابهجا میشه. Google Fonts برعکس، یه قانون latin داره که هر ۹۵ حرف رو پوشش میده.
چرا این کنده؟ مرورگر قبل از کشیدن متن باید اونو shape کنه، یعنی حروف رو با قوانین خود فونت به glyphهای جایگذاریشده تبدیل کنه. shaper کرومیوم یه فونت در هر بار کار میکنه و هر چی فونت اول نتونه بکشه، میره تو صف فونت بعدی. هر فایل فونت تقسیمشده یه فونت جدا حساب میشه. تو تست نویسنده روی ۴۰ پاراگراف انگلیسی با CPU چهار برابر کندتر، دو فایل حدود ۱.۵ برابر و سه فایل حدود دو برابر زمان میبرد. WebKit هم همین الگو رو داشت.
صفحههای عربی بدتر بودن. فونت وب حروف عربی نداشت ولی کاراکتر فاصله داشت، پس فاصلهها از فونت وب و حروف از فونت عربی سیستم میومدن و هر کلمه تکهتکه shape میشد. حتی حذف فونت وب کافی نبود، چون روی macOS، sans-serif فاصله رو از Helvetica و حروف رو از Geeza Pro میگرفت. راهحل این بود که برای عربی یه font stack سیستمی گذاشته بشه که فونت عربی اولش باشه:
:lang(ar) {
font-family: "Segoe UI", "Geeza Pro", sans-serif;
}اولین تلاش نویسنده برای رفع مشکل اوضاع رو چند برابر کندتر کرد: یه فایل لاتین تمیز اضافه کرد و اونو اول CSS گذاشت. طبق مشخصات CSS Fonts، وقتی unicode-rangeها تداخل دارن، آخرین قانون اول بررسی میشه و کرومیوم هم لیست رو از آخر میخونه. پس فایلهای قدیمی که هنوز ادعای حروف لاتین داشتن، برای هر حرف زودتر چک میشدن. با بردن اون قانون به آخر CSS مشکل حل شد.
نکات کلیدی:
- ابزار cn-font-split نسخهی 7.4.3 با تنظیمات پیشفرض، ۹۵ حرف پایهی لاتین رو بین دو فایل از ۲۹۳ فایل تقسیم میکنه.
- کلمهای که به دو فایل فونت نیاز داره حدود ۱.۵ برابر و با سه فایل حدود دو برابر زمان layout میبره.
- با unicode-range تداخلدار، آخرین @font-face اول بررسی میشه؛ فایلی که glyph واقعی رو داره باید آخر بیاد.
- اگه فونت وب یه زبان رو پوشش نمیده، فونت سیستمی همون زبان رو اول font-family بذار؛ فقط حذف فونت وب کافی نیست.
- نسخهی production: یه فایل جدا برای هر خط غربی که آخر CSS میاد، و صفحههای بدون متن چینی دیگه stylesheet بزرگ CJK رو لود نمیکنن.
- عددها از یه مک با CPU کندشدهان و زمان layout رو میسنجن نه خود INP؛ دادهی واقعی کاربرها هنوز نیومده.
- Incremental Font Transfer قراره مشکل kerning بین تکهها رو حل کنه ولی هنوز پیشنویس W3C هست.




