Совместимость с браузерами

Что это такое

Совместимость с браузерами — это практика: решить, в каких браузерах должен работать продукт, выяснить, есть ли в них используемые вами возможности, и обработать те, которых нет. На практике это обнаружение возможностей вместо обнаружения браузера, осознанная матрица поддержки и запасной вариант, который разумно деградирует там, где возможности не хватает.

Почему это важно

Каждую страницу читает набор движков, которые никогда не выпускают одни и те же возможности одновременно. Сайт, предполагающий, что новейший API работает везде, тихо сломается для части аудитории — и обычно в самом незаметном месте: старый корпоративный браузер, заблокированное устройство, пользователь, который никогда не обновляется. Цена игнорирования — не падение, а тихая потеря пользователей, которые не могут выполнить задачу. Урок заслуживает отдельного места потому, что наивное решение — определять user agent и ветвиться по имени браузера — ненадёжно и быстро устаревает, а правильная техника почти ничего не стоит, если применять её с самого начала.

Ключевые идеи

Обнаруживайте возможности, а не браузеры

Спросите движок, что он умеет: в CSS для этого есть @supports, в JavaScript — проверка свойства или объекта, который вы собираетесь использовать. Обнаружение возможностей отвечает на важный вопрос и продолжает работать, когда имя браузера меняет смысл или пользователь его подделывает.

if ("IntersectionObserver" in window) {
  observeVisibility(images);
} else {
  loadAllImages(images);
}

Сначала запасной вариант, потом улучшение

Соберите версию, работающую везде, и уже поверх неё добавьте новое поведение. Это прогрессивное улучшение: отсутствующая возможность стоит отделки, а не функции, — и таблица стилей, которая начинается с простых значений и затем добавляет современное, достигает того же, так что браузер, не понимающий ни одного из них, всё равно что-то отрисует.

.card { width: 100%; }

@supports (display: grid) {
  .card { width: auto; grid-column: span 2; }
}

Держите матрицу поддержки и выводите её из данных

Решите, какие браузеры вы поддерживаете, исходя из аналитики, договорных требований или публичного набора данных о совместимости, запишите это и настройте по нему инструменты. Матрица — вход для всех остальных решений: что транспилировать, какие полифилы включать, какой синтаксис допускать.

Транспиляция переписывает синтаксис, полифилы добавляют поведение

Инструмент может преобразовать новый синтаксис обратно в старый эквивалент, но он не может изобрести отсутствующий API, а полифил — скрипт, который его добавляет. Он стоит байтов каждому посетителю, поэтому включайте их по возможности, а не одним большим бандлом; современный вывод с небольшим legacy-бандлом для остальных — обычный компромисс.

Тестируйте во втором движке

Эмулятор показывает вьюпорт того движка, а не сам движок, поэтому настоящая работа по совместимости включает запуск страницы хотя бы в одном движке, отличном от того, в котором вы разрабатываете, и проверку против самой старой версии из матрицы поддержки, когда цена это оправдывает.

Практика

Оберните одну современную возможность в защиту

Выберите возможность, которой вы пользуетесь не задумываясь, и добавьте рядом запасной путь с обнаружением этой возможности. Заставьте запасной путь сработать, временно отключив проверку.

Готово, когда: запасной путь отрисовывает рабочую страницу, а снятие защиты делает разницу видимой в том же браузере.

Опубликуйте матрицу поддержки и сверьте с ней свой CSS

Запишите браузеры и версии, которые вы поддерживаете, затем просмотрите таблицу стилей на предмет любой возможности, отсутствующей в самом старом из них. Отметьте, что происходит там, где её нет.

Готово, когда: у каждой неподдерживаемой возможности есть либо запасной вариант, либо защита @supports, либо записанное решение принять этот пробел.

Частые ошибки

  • Определение строки user agent — строка подделывается, замораживается вендорами и ничего не говорит о вашем вопросе; исправить: проверяйте саму возможность.
  • Предположение, что современный API существует — страница падает до отрисовки, и запасной путь не срабатывает; исправить: защитите проверкой возможности и дайте старый путь.
  • Полифилы всем и для всего — каждый посетитель платит байтами за случай, который есть у немногих; исправить: отдавайте современный код, а legacy-бандл — только там, где он нужен.
  • Тестирование только в одном движке — различия в раскладке и событиях не видны, пока пользователь не сообщит о них; исправить: перед выпуском прогоните страницу во втором движке.
  • Матрица поддержки, заданная один раз и больше не пересматриваемая — инструменты расходятся с реальностью и собирают под браузеры, которыми никто не пользуется; исправить: пересматривайте матрицу по расписанию, из аналитики, которая её оправдывает.

Что читать дальше

  • Язык гипертекстовой разметки (HTML) (02-frontend/03-html) — слой с самыми старыми и надёжными запасными вариантами из всех.
  • Каскадные таблицы стилей (CSS) (02-frontend/05-css) — @supports и снисходительная обработка ошибок каскада суть инструменты совместимости.
  • JavaScript (02-frontend/06-javascript) — проверки возможностей пишутся на самом языке.