Должна ли библиотека Javascript, использующая функции ES6 и ES7, требовать babel-polyfill?

Я разрабатываю библиотеку, которая активно использует функции ES6 и ES7. Компиляция с помощью Babel приводит к коду, который (естественно) использует такие примитивы, как Symbol или Promise. Должен ли я require('babel-polyfill') убедиться, что такие примитивы точно есть?

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


person Tomas Kulich    schedule 23.01.2016    source источник
comment
Я думаю, все, что сработает, - это вариант на данный момент :)   -  person Tomas Kulich    schedule 23.01.2016
comment
в конечном итоге мы будем требовать babel-polyfill снова и снова - я не вижу, что в этом плохого. Он будет загружен и выполнен только один раз. Именно так работают модули.   -  person Bergi    schedule 23.01.2016
comment
@Bergi, это зависит от того, как npm его устанавливает. Если npm установит его несколько раз, он также будет выполняться несколько раз, что на самом деле приведет к ошибкам, проверьте это: github.com/babel/babel/blob/master/packages/babel-polyfill/src/   -  person Tomas Kulich    schedule 23.01.2016
comment
Кстати, если вы в настоящее время создаете новую библиотеку, вы должны использовать ES2015, чтобы использовать все новые функции, которые нельзя перенести (TCO, модули, прокси). Вскоре будет добавлена ​​поддержка основных браузеров.   -  person Iven Marquardt    schedule 23.01.2016


Ответы (1)


Я провел небольшое исследование по этому поводу:

Требование babel-polyfill изнутри библиотеки выглядит как анти-шаблон; Это по двум причинам:

1) babel-polyfill не любит запрашиваться несколько раз, и если вы попытаетесь это сделать, он выкинет (см. примечание ниже)

2) это приведет к значительному увеличению размера библиотеки, поскольку вам придется многократно связывать полифилл.

И 1), и 2) имеют значение только тогда, когда npm не удается выполнить дедупликацию нескольких babel-polyfill зависимостей. Это может произойти, если вы используете старую версию npm, или дедупликация может быть невозможна из-за ограничений зависимостей. Поскольку последние не так легко контролировать, я считаю и 1), и 2) достаточно серьезными.

А теперь, как вы (вероятно) должны это сделать:

Если вам нужна определенная функция в вашей библиотеке (например, Promise), вы можете require ее конкретно (т.е. не весь полифилл, а только функцию). Этот подход смягчает 1) и частично смягчает 2).

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

Хорошие примеры первого подхода:

https://www.npmjs.com/package/promisify-node

для которого требуется собственная версия совместимого с A+ Promise. Хорошим примером второго подхода является

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 не определен ни браузером, ни полифиллом). Мой совет - не используйте плагин для этой цели.

person Tomas Kulich    schedule 24.01.2016