3D-сцена на сайті — це завжди компроміс між «вау» і мілісекундами. Але компроміс керований: із правильною архітектурою WebGL-фон коштує кілька кілобайтів на старті й нуль мілісекунд блокування рендера.
Розповідаємо, як влаштовані сцени на наших проєктах — включно з цим сайтом.
Канвас живе тільки поруч із в’юпортом
Кожна сцена загорнута в обгортку з IntersectionObserver: канвас монтується, коли блок наближається до екрана, і розмонтовується, коли користувач пішов далі. Це звільняє WebGL-контексти (у браузера їх ліміт ~16) і тримає пам’ять під контролем.
Сцени, які мають бути готові миттєво, монтуються одразу, але поза в’юпортом їхній рендер-луп просто зупиняється: кадри не малюються, батарея не витрачається.
Бюджет кадру і деградація
Правила, яких ми дотримуємось у кожній сцені:
- DPR обмежуємо 1.5 — на ретині різниці майже немає, а пікселів удвічі менше.
- На телефонах зменшуємо кількість частинок у 2–2.5 раза.
- Постобробку не використовуємо: світіння дешевше зібрати адитивним блендингом.
- prefers-reduced-motion — один статичний кадр замість анімації.
- 3D вантажиться окремим чанком після інтерактиву — LCP його не чекає.
Результат
Сторінка з повноцінною частинковою сценою на 20 тисяч точок тримає 90+ у PageSpeed і не гріє телефон. WebGL — не ворог швидкості, якщо ставитися до нього як до фонової музики, а не до головного героя.