15. Mobile Performance
Более 60% веб-трафика — мобильный. Google использует Mobile-First индексацию. Медленный мобильный = потеря трафика и позиций.
Mobile vs Desktop: Разница
Заголовок раздела «Mobile vs Desktop: Разница»CPU: Мобильный в 4-10x медленнее desktopRAM: Меньше, сильнее ограниченаСеть: 4G = 10-30 Mbps, но с высокой задержкой 3G = 1-3 Mbps (ещё используется в регионах!)Батарея: Тяжёлый JS разряжает батареюЭкран: Разные DPR (1x, 2x, 3x)Viewport и Meta
Заголовок раздела «Viewport и Meta»<!-- Обязательно! Без этого Google понизит сайт --><meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Запрет масштабирования (осторожно — плохо для a11y) --><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- Для PWA --><meta name="mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-capable" content="yes">Responsive Images
Заголовок раздела «Responsive Images»<!-- DPR-aware изображения --><img src="photo-800.jpg" srcset=" photo-400.jpg 1x, photo-800.jpg 2x, photo-1200.jpg 3x " alt="Photo">
<!-- Адаптивные по ширине --><img src="photo-800.jpg" srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w" sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 800px" alt="Photo">Touch Targets
Заголовок раздела «Touch Targets»/* ✅ Минимальный размер для касания — 44x44px (Apple HIG) */.button { min-width: 44px; min-height: 44px; padding: 12px 20px;}
/* ✅ Расстояние между кнопками */.button + .button { margin-left: 8px;}
/* ✅ Используйте padding вместо увеличения видимой области */.nav-link { padding: 12px 16px; /* касание работает на всю padding зону */}Быстрый отклик на Touch
Заголовок раздела «Быстрый отклик на Touch»/* ✅ Убираем задержку 300ms на клик (устарело, но ещё встречается) */* { touch-action: manipulation;}
/* ✅ Убираем highlight при касании */* { -webkit-tap-highlight-color: transparent;}
/* ✅ Плавная прокрутка */.scroll-container { -webkit-overflow-scrolling: touch; overflow-y: scroll;}Font Size и Читаемость
Заголовок раздела «Font Size и Читаемость»/* Минимальный размер шрифта — 16px (iPhone зумит если меньше!) */input, textarea, select { font-size: 16px; /* предотвращает автозум на iOS */}
body { font-size: 16px; line-height: 1.5;}
/* ✅ Fluid typography */h1 { font-size: clamp(1.5rem, 5vw, 3rem);}p { font-size: clamp(1rem, 2.5vw, 1.25rem);}Оптимизация для медленных сетей
Заголовок раздела «Оптимизация для медленных сетей»// Определяем тип соединенияconst connection = navigator.connection || navigator.mozConnection;
if (connection) { const { effectiveType, saveData } = connection;
if (saveData || effectiveType === 'slow-2g' || effectiveType === '2g') { // Режим экономии: текст вместо изображений document.body.classList.add('save-data'); }
if (effectiveType === '4g') { // Хорошее соединение — можно грузить полный качество preloadHighQualityImages(); }}
// Адаптивная загрузка видеоfunction loadVideo(src) { const video = document.createElement('video');
if (connection?.effectiveType === '4g') { video.src = src.replace('.mp4', '-hd.mp4'); } else { video.src = src.replace('.mp4', '-sd.mp4'); video.preload = 'none'; // не предзагружаем на медленном }
return video;}/* CSS для Save-Data режима */@media (prefers-reduced-data: reduce) { .hero-video { display: none; } .hero-image { display: block; } /* показываем изображение вместо видео */ .fancy-animation { animation: none !important; }}
.save-data .background-image { background-image: none !important; /* убираем тяжёлые фоны */}Performance бюджет для мобильных
Заголовок раздела «Performance бюджет для мобильных»JavaScript: < 150KB (gzipped)CSS: < 30KB (gzipped)Images (above fold): < 300KBTotal Page Weight: < 1MBTime to Interactive: < 3.8s (3G Fast)// Webpack — предупреждения при превышении бюджетаmodule.exports = { performance: { maxAssetSize: 250000, // 250KB maxEntrypointSize: 400000, // 400KB hints: 'error', },};Анализ реальных пользователей
Заголовок раздела «Анализ реальных пользователей»// Определяем низкопроизводительные устройстваfunction isLowEndDevice() { const memory = navigator.deviceMemory; // GB RAM const cores = navigator.hardwareConcurrency;
return (memory && memory < 2) || (cores && cores < 4);}
// Адаптируем под возможности устройстваif (isLowEndDevice()) { // Отключаем тяжёлые анимации document.body.classList.add('reduce-motion');
// Уменьшаем количество элементов на странице maxItemsPerPage = 10; // вместо 20}/* Уважаем настройки пользователя */@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }}