Pull to refresh
745.56
OTUS
Цифровые навыки от ведущих экспертов

Избушка на обратно-совместимых ножках — компилируем JS для нужных браузеров

Reading time6 min
Views6.1K

image


Привет, хабр! Уже сегодня на otus.ru стартует курс "Fullstack разработчик JavaScript" и я решил поддержать ребят этой статьей. Я кстати сам преподаю на курсе по React.js.

Есть такой принцип — Don't break the web, который можно раскрыть как "веб всегда старается сохранить максимальную обратную совместимость". В некоторой мере этот принцип применим и к веб сайтам и приложениям — ваш сайт должен работать не только в одном конкретном браузере, но в целом наборе разных браузеров и версий. Но в каких? Однозначно должны быть какие-то разумные пределы и IE 6 и netscape navigator поддерживать не стоит, но два вопроса остаются открытыми: какие браузеры вы поддерживаете и как это обеспечить?


Если есть обратная совместимость значит что-то меняется. Меняются в вебе три вещи: ECMAScript (javascript), CSS и различные Web API. CSS мы сегодня оставим на опушке, а пока, тропинка ведет нас в дебри современной фронтенд разработки


Начнем с простого


Так или иначе, абсолютное большинство современных и не очень браузеров поддерживают ES5, этакий greatest common denominator. Большинство библиотек пишутся или скомпилированы в ES5 и мы можем поступить также! Можно либо сразу писать в ES5 (не рекомендую) либо использовать babel или typescript


В сети есть множество туториалов о том как это делать, но позволю себе упомянуть что в babel 7, @babel/preset-es2015 является устаревшим (о чем нам любезно напоминает официальная документация) и рекомендуется использовать @babel/preset-env, которому на самом деле посвящена львиная доля статьи. Но легко поставить избушку на поляне, но мы ведь с вами не за этим здесь собрались, давайте попробуем сделать это на болоте (если почувствовали тоску, то возможно стоит поменять работу)?


Делаем как у больших


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


Дисклеймер: для интеграции @babel/preset-env со стандартной конфигурацией в новый проект не требует понимания того, как эта машинерия работает, но в продакшене все как обычно сложнее и это начинается играть роль

caniuse


https://github.com/fyrd/caniuse


https://caniuse.com/


Также существует в редакции caniuse-lite (именно ее использует browserslist)

Наверное самый известный сайт на который разработчики ходят чтобы узнать в каких браузерах поддерживается необходимая фича. Отдельная его крутость состоит в том, что у них есть данные по использованию браузеров (в том числе и с разбивкой по странам)


browserslist


https://github.com/browserslist/browserslist


С него все начинается. browserslist (browserSlist обратите внимание на S) умеет преобразовывать запрос вида "> 0.25%, not IE11, not dead" в список браузеров, в данном случае означающий все браузеры которые имеют мировую долю использования более 0.25% кроме IE11 и браузеров не получающих обновления безопасности (на момент написания статьи IE 10, IE Mobile 11, BlackBerry 10, BlackBerry 7, Samsung Internet 4 и Opera Mobile 12.1)


corejs


Содержит полифиллы для всех фич ECMAScript вплоть до 2019-й версии. В версии 3 произошло множество глобальных изменений (https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md)


Используется в babel/present-env, поддерживается и 2-я и 3 -я версии


core-js-compat


https://www.npmjs.com/package/core-js-compat


Содержит информацию о том каким браузерам какие полифиллы из corejs нужны. В том числе подключает полифиллы для тех браузеров в которых есть критические баги в фиче. Например до Chrome 80 matchAll не бросал исключение в случае неглобальной регулярки, как нужно по текущему стандарту, хотя имплементация впервые появилась в 73-й версии
https://github.com/zloirock/core-js/blob/master/packages/core-js-compat/src/data.js#L877


compat-table


https://kangax.github.io/compat-table/es6/


Содержит информацию о поддержке фич ECMAScript различными браузерами (думаю понятно) и средами исполнения (nodejs, graalvm etc.)


Используется в @babel/preset-env, но с нюансом — в случае corejs@2 для полифиллов используются данные из compat-table, а в случае corejs@3 — данные из core-js-compat(они более актуальные и умные)


Как это все вообще работает


На практике в классическом варианте все выглядит так:


  1. в .browserslistrc (или в package.json#browserslist) вы указываете browserslist query
  2. в babelrc вы указываете @babel/preset-env в presets и выбираете опцию useBuiltIns (советую entry ибо usage не умеет проверять используемые API в зависимостях)
  3. Эту browserslist query читает @babel/preset-env
  4. @babel/preset-env получает из нее список браузеров через api browserslist и
    4.1 использует compat-data выбирая набор плагинов которые будут применены в вашему коду
    4.2 использует corejs-compat выбирая какие полифиллы подключить

Таким образом на выходе вы получаете js код который будет верно работать во всех указанных браузерах (в разумных пределах ибо есть разные экзотические браузеры про поддержку которых данных просто нет). И наша избушка встает на ножки (или на сваи) и получает обратную совместимость!


И всё?


К сожалению нет, во фронтенде все опять неспокойно. Есть ряд кочек о которые можно легко споткнуться, а то и вообще завязнуть в трясине если сойти с узкой тропинки happy path


browserslist query


Наверняка у проекта в который вы собираетесь это внедрять уже список или хотя бы понимание поддерживаемых браузеров. Если нет, то все просто: возьмите defaults (это > 0.5%, last 2 versions, Firefox ESR, not dead) и вы покроете более 90% вообще всех браузеров (что на самом деле очень хороший результат ибо "все" это вплоть до IE 6!). Если все-таки понимание есть, но надо перевести его (понимание) в query. Это может быть не так-то просто, но главным образом нужно знать три вещи:


  • запятая в browserslist query означает or (то есть "или")
  • "и" записывается как and
  • отрицание записывается как not и при этом применяется через and даже если написано с запятой (если кто-то помнит как заносить отрицание в скобки в булевой алгебре поймет почему)
  • ладно, четыре: можно удобно тестировать вашу query вот тут https://browserl.ist/ (а тут нет S! Жизнь боль)

С этим знанием и внимательным чтением документации (а вы думали можно без этого?) вы сможете подогнать список под ваши нужды. Если будут проблемы, дайте знать в комментариях!


Невиданное-неслыханное


Как сказано выше, defaults это > 0.5%, last 2 versions, Firefox ESR, not dead. Вроде относительно понятно, но если вы посмотрите чему это соответствует то обнаружите там браузеры о существовании которых и не подозревали или не знали что они до сих пор используются. Тем не менее слепо выбрасывать их не стоит, поэтому давайте разберемся с теми которые не входят в большую шестерку с половиной (Chrome, Firefox, Edge, Opera, Safari и IE). Проценты глобального использования приведены для последней версии на момент написания статьи



UPD от Dartess
Там всё очень сложно. На одном только андроиде есть как минимум три версии движка — U2, U3, U4. Все на базе хромиума, но с большими оговорками.
U2 это ультралайтовая и ультралёгкая версия, которая отображает веб, по ощущениям, на уровне IE8. Отключено всё, что можно. В общем, не юзабельно, но возможно было актуально для ультрабюджетных андроидов лет 10 назад.
U3 тоже был направлен на быстродействие и является сильно модифицированной версией хромиума. Тоже местами урезан, но веб в целом работает. На этом браузере встречал некоторые баги, которые не мог воспроизвести ни на одной версии хрома. Отличается широкой поддержкой различных версий андроида и разных процессоров. Плюсом там есть всякие ништяки типа поддержки флеша из коробки и режима сжатия трафика.
U4 появился где-то года три назад, сейчас по умолчанию из маркета в обычной версии ставится он. Является уже самым обычным брендированным хромиумом, поэтому нормально работает и нормально (стабильно) обновляется.
Полный комментарий


  • Baidu Browser, 0%
    И еще один китайский браузер, на этот раз от Baidu (китайский гугл). Судя по всему не получил распространения даже в Китае и данных по поддержке фич естественно нет.
  • KaiOS Browser, 0.2% — https://www.kaiostech.com/
    KaiOS это очень интересный проект — операционная система для очень дешевых смартфонов, призванная сделать технологии доступнее. К сожалению данных по поддержке нет, но я полагаю что можно наладить контакты с разработчиками и узнать. Вообще, rule of a thumb что если данных нет — можно считать что браузер поддерживает ES5

UPD V1tol
По KaiOS проходила информация, что там сейчас используется движок, соответствующий Firefox 48



Что делать с ними ^ решать конечно вам, но я крайне советую стараться поддерживать как можно больше браузеров, это помогает сохранять их разнообразия и не загоняет нас в ловушку IE6 (кхе-кхе Chrome)


Взгляд в будущее


Это уже очень много информации, но мы все еще не коснулись таких вещей как


  • autoprefixer и CSS
  • Свои собственные данные по usage
  • Несколько конфигураций и бандлов
  • Продвинутые опции useBuiltIns

Я надеюсь мы когда-нибудь покроем это в второй части, а пока, всем peace, и пусть ваша избушка не развалится ни в одном браузере! А если вы заинтересовались курсом, то можете узнать о нем подробнее по ссылке.

Tags:
Hubs:
+14
Comments16

Articles

Information

Website
otus.ru
Registered
Founded
Employees
101–200 employees
Location
Россия
Representative
OTUS