Как не загружать desktop-only элементы на mobile
Не начинайте с PHP-определения телефона. Определите, что именно лишнее: пиксели, iframe, module, API или весь компонент — и примените браузерный или серверный механизм с проверяемым fallback.
Самый безопасный путь
Сообщение разработчику
«Сравните mobile/desktop Network и DOM для скрытого компонента. Сохраните его смысл лёгкой mobile-версией. Для картинок используйте picture/srcset, для background — media rule, для JS — matchMedia с conditional import и cleanup, для server variant — fallback и корректный Vary/cache key. Докажите отсутствие ненужных запросов, а не только display:none».
Сохраните шаблон, CSS/JS entry points, текущие скриншоты и список действий. Зафиксируйте контрольные viewport и поведение при resize/orientation; работайте в тестовой среде.
Пошаговая настройка
- Откройте mobile viewport до загрузки, очистите кеш и запишите HAR. Найдите запросы скрытого компонента и их initiator.
- Решите, можно ли удалить компонент без потери информации, навигации, формы, рекламы или юридического текста.
- Для той же картинки разных размеров добавьте
srcset/sizes; для разных композиций —pictureс fallback. - Background задавайте только внутри подходящего media query; удалите безусловный preload desktop-фона.
- Тяжёлый JS не импортируйте на mobile. Лёгкий bootstrap проверяет media query, загружает module на desktop и умеет уничтожить его при смене режима.
- Если сервер отдаёт разные HTML, не доверяйте только User-Agent: предусмотрите default/fallback, Client Hints при наличии и корректное разделение CDN-кеша.
- Повторите загрузку с нуля, resize, orientation, back/forward, keyboard и важные действия на обеих версиях.
Технические примеры
Условная JS-инициализация
const query = matchMedia('(min-width: 64rem)');
let cleanup;
async function sync() {
if (query.matches && !cleanup) {
cleanup = (await import('./desktop-slider.js')).mount();
} else if (!query.matches && cleanup) {
cleanup(); cleanup = undefined;
}
}
query.addEventListener('change', sync);
sync();Responsive image
<picture>
<source media="(min-width: 64rem)" srcset="hero-wide.webp">
<img src="hero-mobile.webp" alt="Описание"
width="720" height="900">
</picture>Если mobile вообще не должен показывать изображение, не подменяйте его прозрачным пикселем без необходимости: удалите весь необязательный компонент из соответствующей ветки и сохраните альтернативный смысл в HTML.
Риски и откат
| Симптом | Причина | Действие |
|---|---|---|
| Desktop module всё равно в mobile bundle | Статический import или общий entry | Использовать отдельный dynamic chunk |
| После поворота два слайдера | Нет cleanup/idempotent mount | Добавить уничтожение и защиту |
| CDN показывает не ту версию | Неверный cache key/Vary | Откатить variant и исправить кеш |
| На mobile пропала важная функция | Компонент сочли декоративным | Вернуть лёгкую доступную альтернативу |
Для отката верните общий шаблон/entry, очистите затронутый кеш и повторите обе версии. После выпуска выполните независимую проверку. Полный redesign и глобальный bundle refactoring оцениваются отдельно.