Autopolyfiller — Precise polyfills


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

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

    Есть целый ряд способов исправить эту ситуацию:

    lodash и underscore


    Это достаточно популярный способ «починить» браузеры на сегодняшний день, плюс ко всему lodash приносит ряд полезных функций для работы с данными. К тому же он позволяет беречь нервы разработчиков, которые до сих пор боятся менять прототип базовых классов «во благо».

    _.chain([1, 2, 3, 4])
    .map(function (item) {
        return item * item;
    })
    .filter(function (item) {
        return item < 9;
    })
    .value();
    


    Лично мне он не нравится из-за того, что lodash делает код «зашумленным». Но это дело каждого.

    es5shim


    es5shim чинит практически все отсутствующие функции, которые были утверждены в спецификации ES5. Вам достаточно подключить файл es5-shim.js и можно свободно пользоваться практически всеми благами EcmaScript 5.

    [1, 2, 3, 4]
    .map(function (item) {
        return item * item;
    })
    .filter(function (item) {
        return item < 9;
    });
    

    Такой код, безусловно, выглядит гораздо чище.

    polyfill.io


    Суть очень проста. Вы включаете в ваш html код скрипт, который динамически генерируется исходя из заголовка User-Agent браузера клиента и чинит все, что в нем поломано:

    <script src="//polyfill.io"></script>
    

    (не используйте эту ссылку в Production)

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

    Сам проект polyfill.

    Autopolyfiller


    Предыдущие способы починки JavaScript имеют значительный недостаток. Они заставляют вас думать. Точнее самостоятельно разрешать все зависимости вашего кода, учитывая версии поддерживаемых браузеров (подключать какие-то дополнительные скрипты). Либо могут разбиться о реальность www. Да и именно по этому многие разработчики включают весь es5shim (без спец сборок) и боятся его отключить после отказа от поддержки IE8 (а мало ли что сломается). Проект постепенно обрастает лишними зависимостями и вычищать эти зависимости очень-очень больно.

    Как вариант, можно создать какой-то файл в котором хранить все используемые ES5 методы. И при добавлении нового метода в код расширять этот файл, учитывая все версии поддерживаемых браузеров. Используя этот список, можно получить кастомную сборку es5shim. А как быть если мы повышаем версию браузеров, удаляем используемый метод? Писать скрит? В общем, шило на мыло.

    Если посмотреть с другой стороны, то ваш код — это и есть тот самый файл со списком зависимостей, просто этот список не явный:

    [1, 2, 3, 4]
    .map(function (item) {
        return item * item;
    })
    .filter(function (item) {
        return item < 9;
    });
    

    Мы можем легко понять, что в этом коде используется 2 функции из ES5: Array.prototype.map и Array.prototype.filter.

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

    Из этой простой идеи родился проект Autopolyfiller, который помогает вам не думать. Как вы уже заметили его название схоже с Autoprefixer, который исповедует те же принципы, но касательно CSS.

    Алгоритм работы Autopolyfiller очень прост:
    — Вы определяете список браузеров, которые поддерживает ваш проект (это не оябзательно)
    — Скармливаете Autopolyfiller'у ваш код
    — Autopolyfiller разбирает AST и находит методы ES*
    — Убирает методы, которые вам не нужны, используя список браузеров
    — Вы получаете код с полифиллами

    Из-за того, что JavaScript это интерпретируемый язык, Autopolyfiller может промахнуться в некоторых очень граничных случаях.

    — В этом коде $('div').map() он найдет Array.prototype.map.
    — В этом коде eval('Object.keys(this)') и этом коде Object['k' + 'eys']() он ничего не найдет.

    Но если не делать ничего странного и не использовать eval-подобные структуры, то его точность будет достаточно высока.

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

    Кроме консольной утилиты и API, на данный момент написаны таски под Gulp, Grunt и Enb. Так, что вы можете легко прикрутить Autopolyfiller в ваш сборочный процесс уже сегодня. А если вы все еще сомневаетесь — попробуйте демку!

    Ссылки:
    Проект Autopolyfiller на Github
    Качество кода Autopolyfiller
    Демо Autopolyfiller

    Буду рад ответить на все ваши вопросы.
    • +43
    • 11,2k
    • 5
    Поделиться публикацией

    Похожие публикации

    Комментарии 5
      +2
      Прикольно.

      Только одно на понимаю: Допустим я использую String.prototype.trim и поддерживаю последний Chrome и IE8.

      Autopolyfiller пойдет в репозиторий полифилов и воткнет вот это в мой код:
      // String.prototype.trim
      String.prototype.trim = function trim() {
      	return this.replace(/^\s+|\s+$/g, '');
      };
      


      Получается, что даже если я запущу код в хроме, нативная версия будет перезаписана полифилом и не будет использована?

      Я понимаю, что это косяк источника полифила, а не Autopolyfiller'a, но может как-то оборачивать полифилы и применять только если нету нативных методов?
      Или эта функциональность уже есть?
        +2
        Нет, при генерации кода Autopolyfiller их обернет в if () {}. Репозиторий же хранит полифилы в чистом виде (да это может смущать).
        +3
        Самое лучшее решение! Как и autoprefixer для css, вместо набора миксинов.
          0
          в принципе, подход интересный. но, как вы сами заметили, вносит в сборку некоторую степень неопределенности. а в нашем деле определенность это главное. :)
          es5shim по указанной ссылке весит 14,5К в минифицированном виде, и 5К пожатым gzip. это цена вопроса, или есть еще какие-то основания?
            0
            Вопрос думать о зависимостях или нет. Если не использовать eval, то я могу гарантировать, что нет никаких подводных булыжников. Просто потыкайте в демку ;)

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое