Добро пожаловать в ад Polyfill 😱🔥🚒

Несмотря на то, что Microsoft мудро решила прекратить поддержку старых версий IE с января прошлого года, IE11 все еще существует (и, возможно, официально до 2015 года). Раньше количество пользователей IE11, несомненно, уменьшится, но на данный момент оно по-прежнему составляет 5,49% браузеров, обращающихся к нашему ресурсу, поэтому нам необходимо учитывать их.

Webcomponentsjs

Это легкая часть. Полифиллы доступны для обеспечения функциональности в соответствии со спецификациями v1 (я смотрю на вас, Firefox). `webcomponents-loader.js` динамически загружает минимальный пакет, используя обнаружение функций, поэтому вы можете спокойно спать, зная, что вы не добавите много нагрузки. Вот и все, функциональность веб-компонентов упорядочена.

<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js" charset="utf-8"></script>

Вавилон

Чтобы ваш прекрасный код ES2016 работал во всех браузерах, вам необходимо его транспилировать, и Babel - лучший инструмент для этого. Недавно они сделали доступным babel-preset-env:

Пресет Babel, который компилирует ES2015 + до ES5, автоматически определяя плагины и полифиллы Babel, которые вам нужны, в зависимости от вашего целевого браузера или среды выполнения.

Это довольно круто, так как вам просто нужно указать, для каких браузеров вы хотите выполнить транспилирование, а предустановка автоматически определяет, какие функции требуются. Для IE11 это приводит нас к ES5. Вот как выглядит мой .babelrc (я использую rollup для создания и упаковки своего настраиваемого элемента).

{
    "presets": [
        [
            "env", {
                "targets": {
                    "ie": 11
                },
                "modules": false
            }
        ]
    ],
    "plugins": [
        "external-helpers"
    ]
}

Теперь у нас есть транспилированный код, но по-прежнему нужен полифилл babel для обеспечения недостающей функциональности.

<script src="node_modules/babel-polyfill/dist/polyfill.min.js"></script>

Пока все хорошо, теперь у нас есть полифиллы и транспилированный код, понятный IE11. Но…

Какого черта? Он работает в IE11, но больше не работает в Chrome !? 🙀

Что там произошло, я слышал, вы говорите? Ну, Chrome изначально поддерживает настраиваемые элементы v1, а собственные элементы - это классы ES6. При расширении класса ES6 вы должны вызвать super (), а в ES5 нет способа сделать это, что означает, что наш транспилированный код не работает в Chrome. Но ждать! Что это входит в состав webcomponentsjs? custom-elements-es5-adapter.js спешит на помощь!

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

<script src="node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js" charset="utf-8"></script>

Принести

Если ваш компонент имеет дело с асинхронной загрузкой данных, вам, вероятно, понадобится и его Polyfill.

<script src="node_modules/whatwg-fetch/fetch.js" charset="utf-8"></script>

Вывод

Довольно много дополнительных зависимостей, но теперь мы можем предоставить настраиваемые элементы v1 всем нашим пользователям, и мы по-прежнему можем писать наш код с последними функциями ES. Это также означает, что когда количество пользователей IE11 станет достаточно маленьким, мы можем просто удалить полифилы и изменить цель babel-env, не меняя код. Очевидно, имеет смысл использовать условную загрузку для custom-elements-es5-adapter.js и fetch.

Обновлять

Я создал генератор Yeoman, который сделает все это за вас: https://www.npmjs.com/package/generator-rollup-customelement

Хотелось бы услышать ваши мысли ниже. Если вы нашли это полезным, пожалуйста, хлопните в ладоши!