Self-hosted варіативні шрифти у вебзбірці Expo
У спільній кодовій базі для iOS, Android і вебу шрифти — це той ресурс, де платформи справді розходяться. Нативу потрібен файл шрифту, вкладений у збірку й зареєстрований. Вебу потрібен якнайменший файл, відданий з власного домену, і щоб браузер дізнався про нього якомога раніше. Expo згладжує цю різницю, беручи шрифти на себе, — і на вебі віддає не те, що ви обрали б самі.
Що Expo робить на вебі
expo-font реєструє шрифти в рантаймі. На вебі це означає, що правило
@font-face збирається в JavaScript і вставляється в документ уже після старту
застосунку. Вказує воно на той файл, який ви передали, а для кросплатформного
проєкту це майже завжди TTF — бо саме він потрібен нативній частині.
Звідси два наслідки, і обидва коштують реальних мілісекунд:
TTF у вебі — це марнування. Той самий шрифт у WOFF2 зазвичай удвічі менший або й більше, бо WOFF2 стиснутий Brotli за самою специфікацією. Ви віддаєте формат, який існує для іншого середовища.
@font-face, вставлений у рантаймі, неможливо виявити рано. Preload-сканер
браузера читає HTML ще до виконання скриптів. Шрифт, оголошений у початковому
CSS, починає завантажуватись одразу; оголошений скриптом після гідратації — ні.
На першому візиті через повільне з'єднання це різниця між швидкою підміною
тексту й помітним відрізком із фолбек-шрифтом.
Що робити натомість
Оголосити шрифт самому — у CSS, який іде разом із документом:
@font-face {
font-family: "Inter";
src: url("/fonts/inter-variable.woff2") format("woff2-variations");
font-weight: 100 900;
font-display: swap;
}
Варіативний шрифт тут важливіший, ніж здається. Кросплатформному інтерфейсу зазвичай потрібні три-чотири накреслення; як окремі файли це три-чотири запити й три-чотири кеші. Як один варіативний WOFF2 — це один файл на весь діапазон, і часто він менший за два статичні накреслення разом.
Далі — сказати про нього браузеру в head, щоб завантаження починалося разом із HTML, а не після нього:
<link
rel="preload"
as="font"
type="font/woff2"
href="/fonts/inter-variable.woff2"
crossorigin
/>
Атрибут crossorigin не є необов'язковим навіть для файлу з того самого
домену: шрифти завантажуються в режимі CORS, і без нього preload-запит і
справжній запит вважаються різними. Файл приїде двічі й не допоможе нікому.
Частина, на яку насправді йде час
Зробивши все це, ви маєте два оголошення того самого сімейства: своє в CSS і те, яке Expo вставляє в рантаймі. Браузер спокійно завантажить обидва. Робота полягає в тому, щоб натив залишив свою реєстрацію шрифту, а веб її пропустив, — тобто в розділенні платформ саме там, де шрифти завантажуються, замість одного спільного виклику, який вдає, що платформи однакові.
Ось і весь трюк, і він невеликий. Робити його варто тому, що він лежить на шляху першого рендера для кожного відвідувача, і тому, що спільна кодова база легко змушує забути: «один виклик, який працює всюди» іноді означає «один виклик, який тихо помиляється на одній платформі».
Чи було воно того варте
Для абонентського кабінету — так. Люди відкривають його переважно з телефона, на мобільному інтернеті, щоб глянути баланс. Це найгірший сценарій для шрифту, який починає вантажитись пізно й нічого не блокує, але сприймається як повільність.
Для внутрішнього інструмента, який ніхто не відкриває «з холодного старту», — радше ні. Прийом дешевий, але не безкоштовний, а вся вигода — у першому візиті.
- Expo
- React Native Web
- Продуктивність
- Шрифти