Кроссбраузерная совместимость HTML5-игр: тест-матрица
1) Почему у HTML5-игр «болит» кроссбраузерность
Игры затрагивают почти все слои платформы: графику (Canvas/WebGL/WebGPU), таймеры и потоки (RAF/Workers), звук (WebAudio/Media policies), ввод (keyboard/pointer/touch/gamepad), сеть и кеши (SW/Cache/IndexedDB), интеграцию (fullscreen/orientation/PWA). Разнобой движков — Chromium (Chrome/Edge/Opera/Android), WebKit (Safari/macOS, iOS/iPadOS во всех браузерах), Gecko (Firefox). Плюс различия энергосбережения, throttling фоновых вкладок, лимиты памяти и автоплей-политики.
2) Поддерживаемые окружения: целевая матрица
Браузеры/ОС (минимальные версии — пример, подставьте свои SLA):- Desktop: Chrome/Edge 116+, Firefox 115+, Safari 16+ (macOS 12+).
- Mobile: Chrome Android 116+ (Android 9+), Samsung Internet 21+, Safari iOS/iPadOS 16+.
- WebView: Android WebView 116+, iOS — только WebKit (все браузеры на iOS используют WebKit).
- PWA (установка): Chromium desktop/mobile, Safari iOS 16.4+ (Add to Home Screen с ограничениями).
- Низкий (мобильные бюджетные, 2 ГБ RAM)
- Средний (мобильные/ультрабуки, 4–8 ГБ RAM)
- Высокий (десктоп/консумерные GPU, 8–16+ ГБ)
3) Большая тест-матрица (шаблон)
Сформируйте реальную таблицу в своём трекере. Ниже — ключевые блоки и статусы (OK/Partial/N/A), которые нужно замерять.
3.1 Графика
3.2 Аудио и медиа-политики
3.3 Ввод и интерфейс
3.4 Производительность и энергосбережение
3.5 Сохранения/офлайн/сеть
4) Минимальный набор ручных сценариев (Smoke)
1. Первый запуск: загрузка ассетов, splash, старт уровня < 3 с на среднем классе.
2. Ввод: тач/мышь/клава/геймпад, множественные пальцы, удержание, свайпы.
3. Экран: полноэкран, блокировка ориентации, safe-area (iPhone с челкой).
4. Аудио: первая нота после пользовательского жеста, mute/unmute, микс музыки/FX.
5. WebGL: потеря/восстановление контекста (симулировать), тени/шейдеры/масштаб.
6. Жизненный цикл: свернуть/развернуть, звонок/уведомление, вкладка в фоне.
7. Сохранения: прогресс/настройки в IndexedDB/LocalStorage, восстановление после перезапуска/офлайна.
8. Сеть: 3G throttle/высокий RTT, потеря сети, ретраи, кеширование через SW.
9. PWA: установка (Chromium/iOS), иконки, offline-страница, обновление версии.
10. Долгая сессия: 20–30 минут без утечек (FPS/heap стабильны).
5) Автоматизация: чем и как
Playwright (рекомендуется): кросс-движок, мобильные эмуляции, WebKit-драйвер, видео/трейсы.
Cypress: быстрый dev-цикл, но WebKit/мобайл — ограниченно.
WebDriver/Selenium: интеграция с облаками.
Облака: BrowserStack, Sauce Labs — реальные устройства и iOS Safari.
Профилирование: Chrome DevTools Protocol, Safari Web Inspector (Remote), Firefox Profiler.
Перф-скрипты: k6/browser для RUM-подобных сценариев загрузки ассетов.
Совет: держите «пакет» автотестов на 3–5 минут (smoke) для каждого PR: загрузка, один игровой цикл, пауза, переключение ориентации, проверка сохранения.
6) Производительность: целевые метрики и телеметрия
FPS: стабильные 60 fps (или 120 на ProMotion) — фиксируйте frame pacing, а не только среднее.
Frame budget: 16.7 мс (или 8.3 мс) на update+render, GC < 2–3 мс в кадре.
Input latency: < 80 мс мобайл, 50 мс десктоп.
Time-to-First-Frame (TTFF): < 1.5 с (после загрузки ассетов).
Heap рост: не более +10% за 20 минут сессии; отсутствие runaway allocations.
Аудио latency: < 100 мс roundtrip.
Встройте RUM: отправляйте телеметрию FPS, TTFF, heap, WebGL context lost, ошибок рендеринга по `browser/os/device`.
7) Частые несовместимости и как лечить
7.1 Графика/рендер
HiDPI Canvas: задавайте логический размер = CSS px, физический = `css devicePixelRatio`.
WebGL контекст lost: слушайте `webglcontextlost/webglcontextrestored`, храните ресурсы для перезагрузки.
Текстуры/шейдеры: избегайте неуниверсальных расширений; проверяйте `OES_texture_float`, `EXT_color_buffer_float` и fallback.
WebGPU: катите feature-flag; держите WebGL2 путь как fallback.
7.2 Аудио/автоплей
Запускайте AudioContext по пользовательскому жесту (`tap/click`) и храните флаг «разрешено».
На iOS готовьтесь к suspend при сворачивании/переключении.
7.3 Ввод/жесты
Слушатели событий делайте passive по умолчанию; где нужно `preventDefault()` — явное отключение passive.
Pointer Events + Touch Events — избегайте двойной обработки; абстрагируйте слой ввода.
Gamepad: проверяйте `navigator.getGamepads()` по RAF, учитывайте раскладку кнопок.
7.4 Fullscreen/Orientation/Safe-Area
Для iOS учитывайте `env(safe-area-inset-)`, добавьте padding к канвасу/Overlay UI.
Orientation lock только после user gesture; имейте кнопку «повернуть экран».
7.5 Сториджи/офлайн
IndexedDB: оборачивайте операции в тайм-ауты/ретраи; на iOS квоты малы — держите легковесные сохранения.
Service Worker: стратегия `Stale-While-Revalidate` для ассетов; честно инвалидируйте версии (контент-hash).
LocalStorage может быть недоступен в приватных режимах — деградируйте к памяти с предупреждением.
7.6 Таймеры/фон
В фоне таймеры клампятся до 1 с и более. Останавливайте тяжелую логику, паузьте игру.
Включайте page visibility/`visibilitychange` и event-driven обновления вместо интервалов.
8) Пайплайн сборки под кроссбраузер
Транспиляция: TypeScript/Babel таргеты `es2020` (или ниже для старых WebViews).
Полифиллы: только по детекту фич (feature detection), а не по UA.
Ассеты: спрайт-листы, текстуры с fallback форматами (WebP/PNG), аудио (AAC/OGG/Opus).
Разделение кода: lazy-chunks для редактора/неигровых панелей.
Сжатие: Brotli/Zstd; HTTP/2/3; CDN с immutable-версированием.
Feature flags: WebGPU/OffscreenCanvas/Threads — включайте по белому списку.
9) Шаблоны чек-листов
9.1 Смартфон (Android/Chrome, iPhone/Safari)
- Touch + multi-touch; жесты не «дергают» страницу
- Fullscreen и ориентация; safe-area верная
- Первый звук после тапа; mute работает
- FPS ≥ 50 (низкий класс), без «рваного» кадра
- Сохранение/восстановление прогресса после перезапуска
- Офлайн сценка/перезапуск SW
- Вызов системных оверлеев (входящий звонок) → корректная пауза
9.2 Десктоп (Windows/macOS)
- Мышь + колесо + клавиатура, IME
- Геймпад (XInput/Generic)
- 60/120 Гц мониторы: стабильный frame pacing
- Alt-Tab/несколько мониторов/fullscreen/windowed
- Память < лимита, без утечек (20+ минут)
10) Примеры кода (фрагменты)
Canvas с HiDPI:js function resizeCanvas(canvas) {
const dpr = Math.min(window.devicePixelRatio          1, 2);
const { clientWidth:w, clientHeight:h } = canvas;
canvas.width = Math.floor(w dpr);
canvas.height = Math.floor(h dpr);
const ctx = canvas.getContext('2d');
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
}js const gl = canvas.getContext('webgl', { preserveDrawingBuffer:false });
canvas.addEventListener('webglcontextlost', e => { e.preventDefault(); paused = true; });
canvas.addEventListener('webglcontextrestored', () => { reloadResources(); paused = false; });js let audioUnlocked = false;
window.addEventListener('pointerdown', () => {
if (!audioUnlocked) {
const ctx = new AudioContext();
const b = ctx.createBuffer(1, 1, 22050);
const s = ctx.createBufferSource();
s.buffer = b; s.connect(ctx.destination); s.start(0);
audioUnlocked = true;
}
}, { once:true, passive:true });js document.addEventListener('visibilitychange', () => {
if (document.hidden) pauseGame();
else resumeGame();
});11) Управление рисками и приоритезация
Закон Мёрфи для iOS: тестируйте каждую минорную версию iOS из вашей матрицы — регрессии часты.
WebView OEM: Android-девайсы с устаревшими WebView — отдельный слой рисков (введите «greylist» устройств).
Функциональные флаги: проблемные фичи включайте по брендам/рынкам-пилотам.
Rollout: 1% → 10% → 50% → 100% с RUM-гейтами (FPS, crash, TTFF).
12) Наблюдаемость и баг-репорты
В каждый отчёт о баге включайте: `ua`, `browser version`, `os`, `device`, `gpu/renderer`, `memory`, `fps`, `logs (ошибки WebGL/WebAudio)`, `steps`, `repro video`.
Автоматическая отправка crash dumps (ошибки JS/ресурсы), событий `context lost`, `audio unlock failed`.
Дашборды: FPS по браузерам/девайсам, средний TTFF, доля context lost, ошибки IndexedDB, офлайн-хиты SW.
13) Итоговый шаблон матрицы (CSV-рыба)
Platform,Browser,Version,Feature,Scenario,Expected,Status,Notes
Android,Chrome,116+,WebGL2,Context lost/restore,State restored,OK, iOS,Safari,16.6,Audio,First sound on tap,Plays,PARTIAL,Silent switch affects
Desktop,Firefox,115+,Fullscreen,Enter/Exit,No layout jump,OK, Android,WebView,116+,Storage,IndexedDB quota,Save 5MB,PARTIAL,Quota lower on device X iOS,Safari,16.4+,PWA,Install & relaunch,State persisted,OK, ```
---
14) Чек-лист продакшен-готовности
[] Зафиксирована матрица браузеров/версий/устройств и SLA обновления.
[] Smoke-набор автотестов (Playwright) запускается на PR и nightly; отчёты с видео/трейсами.
[] RUM-телеметрия FPS/TTFF/heap/WebGL-ошибки с разрезом по браузерам/девайсам.
[] Фолбэки: WebGL1 ← WebGL2 ← WebGPU; Audio unlock; Pointer/Touch абстракция.
[] Обработаны lifecycle/visibility, pause/resume, offline, context lost.
[] Сохранения устойчивы (IndexedDB + деградация), версия ассетов immutable через SW/CDN.
[] Профили на реальных устройствах (iOS/Android) и десктопах 60/120 Гц.
[] Документация известных ограничений (iOS автоплей, квоты IDB, orientation).
[] Планы отката/feature-flags для проблемных фич (WebGPU/Threads).
[] Канал обратной связи в игре (feedback + лог-дамп).
---
Резюме
Кроссбраузерная совместимость HTML5-игр — это не один чек-бокс «работает в Safari», а дисциплина: жёсткая матрица платформ, измеримые метрики (FPS/TTFF/heap), автотесты на реальных девайсах, фолбэки графики/аудио/ввода и бережная работа с офлайном и сохранениями. Введите стабильный пайплайн тестирования, собирайте RUM и держите фичи за флагами — так игра будет одинаково плавной и предсказуемой на Chrome, Safari и Firefox, на телефоне и десктопе.