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