Кросбраузерна сумісність 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, на телефоні і десктопі.