Должна ли библиотека Javascript, использующая функции ES6 и ES7, использовать babel-polyfill?
Я занимаюсь разработкой библиотеки, в которой интенсивно используются функции ES6 и ES7. Компиляция этого с Babel приводит к коду, который (естественно) использует примитивы, такие как Symbol или Promise. Нужно ли мне require('babel-polyfill')
чтобы убедиться, что такие примитивы есть наверняка?
В первый момент ответ кажется "да" - особенно если я не знаю, в какие среды выполнения кто-то может выполнить мою библиотеку. С другой стороны, если каждая библиотека делает это, мы в конечном итоге потребуем babel-polyfill
снова и снова (и я не уверен, что это хорошая идея).
1 ответ
Я провел некоторое исследование по этому вопросу:
требующий babel-polyfill
изнутри библиотека выглядит как анти-шаблон; Это по двум причинам:
1) babel-polyfill
не хочет, чтобы его требовали несколько раз, и он выдаст, если вы попытаетесь это сделать (см. примечание ниже)
2) это приведет к значительному увеличению размера библиотеки, так как вам придется объединять полифилл несколько раз.
Оба пункта 1) и 2) актуальны только тогда, когда npm
не в состоянии дедупликации нескольких babel-polyfill
зависимостей. Это может произойти, если вы используете старую версию npm
или дедупликация может быть невозможна из-за ограничений зависимости. Поскольку последним нельзя легко управлять, я считаю 1) и 2) довольно серьезным.
А теперь, как вы (вероятно) должны это сделать:
Если вам нужна определенная функция в вашей библиотеке (например, Promise), вы можете require
это конкретно (т.е. не весь polyfill, просто функция). Этот подход смягчает 1) и частично смягчает 2).
Вероятно, лучший способ сделать это - просто предупредить своих пользователей, что ваша библиотека ожидает некоторые функции ES6, поэтому они должны требовать полифилла.
Хорошие примеры первого подхода
https://www.npmjs.com/package/promisify-node
для которого требуется собственная версия Promise, совместимого с A+. Хороший пример второго подхода
https://github.com/ubolonton/js-csp
который использует генераторы, но не делает ничего, чтобы гарантировать, что они действительно есть (в общем, просто компиляции кода с помощью Babel недостаточно, и для их работы требуется полифилл).
-------- РЕДАКТИРОВАТЬ --------
Я узнал что babel-plugin-transform-runtime
может быть использован именно для этой проблемы: он позволяет использовать функции ES6 / ES7, не затрагивая глобальное пространство имен, требуя полизаполнения. Грустная часть истории заключается в том, что этот плагин чрезвычайно глючит, вероятно, потому что это принципиально сложно сделать работу. Например:
Object.keys({})
превращается в нечто похожее на:
var _keys=require("babel-runtime/core-js/object/keys")
_keys(obj)
но
var aaa = Object
aaa.keys(obj)
не преобразуется вообще и, следовательно, потерпит неудачу (если Object.keys не определен ни браузером, ни полифилом). Мой совет - не используйте плагин для этой цели.