С несколько недавним выпуском Babel 6 произошел довольно резкий сдвиг по сравнению со старыми версиями, в котором каждый компонент был разделен и уменьшен. Это упрощение является фантастическим с точки зрения ответственности компонентов, но сбило с толку ряд пользователей. Отчасти путаница происходит из-за огромного количества образовательных ресурсов, не соответствующих версии, включая документацию от сторонних производителей, которые, возможно, были действительны для Babel 5, но больше не соответствуют действительности.

Прежде чем я начну, я скажу, что весь набор очень удобочитаем. Вы можете ясно увидеть, за что отвечает каждый компонент, просмотрев код.

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

npm установить babel

Сам модуль babel больше не используется, поскольку он разбит на несколько других пакетов. Это не тот модуль, который вам нужен.

npm установить babel-core

babel-core, что неудивительно, является компилятором ядра для babel. Это то, что облегчает выполнение кода через серию определяемых вами преобразований. По умолчанию он не поставляется с какими-либо преобразованиями, поэтому вы должны установить и зарегистрировать свои собственные.

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

Различие между тем, что должно быть облегчено преобразованием, и тем, что может быть полифиллировано - и, следовательно, тем, что требует конкретного преобразования бабеля по сравнению с одним из решений полифиллинга, упомянутых ниже, - заключается в том, можете ли вы повторно реализовать эту функцию сегодня в ES5. Например, Array.from можно записать на ES5, как продемонстрировано на MDN, но я не могу ничего написать в ES5, чтобы добавить синтаксис стрелочной функции в JavaScript. Следовательно, существует преобразование для стрелочных функций, но отсутствует для Array.from - оно должно быть предоставлено отдельным полифилом, например babel-polyfill или babel-runtime (с преобразованием времени выполнения, как описано ниже).

Babel 6 представил концепцию предустановки, которая является сокращением для набора преобразований. Если вы ищете общий случай поддержки функций es2015, вам нужно установить и зарегистрировать модуль babel-preset-es2015.

Пресеты можно использовать (после их установки), зарегистрировав их в файле .babelrc следующим образом:

{
  "presets": ["es2015"]
}

npm установить babel-cli

Если вы хотите использовать какие-либо инструменты командной строки, которые ранее поставлялись с babel, вам нужно установить модуль babel-cli.

babel-cli поставляется с четырьмя исполняемыми файлами: babel-doctor, babel, babel-node и babel-external-helpers.

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

babel - это интерфейс командной строки для преобразования вашего кода, использования файлов или папок в качестве входных данных, выполнения ваших зарегистрированных преобразований для них (с использованием babel-core) и их вывода, либо на консоль, либо на диск.

babel-node - это удобный двоичный файл, который не предназначен для производственного использования. Подобно двоичному файлу node, его можно использовать для запуска сценария, если он указан в командной строке, или как REPL, если не указаны аргументы. Он автоматически требует babel-polyfill для полифилляции функций и методов ES2015 и настраивает babel-register для компиляции (т. Е. Преобразования) других модулей по мере необходимости. См. Ниже информацию об обоих.

npm установить babel-register

babel-register - это обработчик require для babel. Он заменяет механизм загрузки файлов * .js узлом при необходимости собственным механизмом. Проще говоря, если модуль не является частью ядра узла и не находится в node_modules /, babel попытается скомпилировать его в нужное время. В противном случае он возвращается к узлу для запроса модуля. Теоретически это приведет к небольшому увеличению использования памяти, так как ваши файлы будут кэшироваться дважды - один раз в кеш модуля узла и один раз в кеш-память babel, но на практике это незначительно. Кроме того, скомпилированные модули могут быть кэшированы на диск по завершении процесса, что означает, что в некоторых случаях вам не придется нести расходы на компиляцию во второй раз.

npm установить babel-polyfill / npm установить babel-runtime

Это, возможно, наиболее часто неправильно понимаемые модули в экосистеме Babel.

В Babel 6 ничто (за исключением двоичного файла babel-node) не будет автоматически объединять функции ES2015 за вас. Вам придется полифиллировать их самостоятельно, а это значит, что вам почти всегда понадобится babel-polyfill или babel-runtime.

Модули babel-polyfill и babel-runtime используются для выполнения одной и той же функции двумя разными способами. Оба модуля в конечном итоге служат для имитации среды ES6. Как упоминалось выше в разделе babel-core, это вторая половина уравнения - функции, которые необходимо полифицировать, а не просто преобразовывать (например, глобальные ключевые слова, методы прототипов и т. Д.).

И babel-polyfill, и babel-runtime эмулируют среду ES2015 с двумя вещами: множеством полифилов, предоставляемых core-js, а также полным генератором время выполнения (который дает вам поддержку генератора / выхода).

babel-polyfill выполняет эту задачу, присваивая методы прототипам глобальных или собственных типов, что означает, что при необходимости, с точки зрения используемой среды выполнения javascript, методы и объект ES2015 просто существуют. Если, например, вы должны были потребовать babel-polyfill в сценарии, запущенном под узлом v0.10 - среда выполнения, которая изначально не поддерживает Promise API - тогда ваш скрипт получит доступ к объекту Promise. Что касается вас, автора, вы внезапно используете среду, поддерживающую объект Promise.

babel-runtime делает нечто очень похожее, но не загрязняет прототипы собственных объектов или глобальное пространство имен. Вместо этого babel-runtime - это модуль, который вы можете указать как зависимость вашего приложения, как и любой другой модуль, который дополняет методы ES2015. Другими словами, продолжая приведенный выше пример, хотя у вас может не быть доступного объекта Promise, теперь у вас есть те же функции, которые доступны вам из require ('babel-runtime / core -js / обещание '). Само по себе это полезно, но неудобно. К счастью, babel-runtime не предназначена для использования сама по себе. Напротив, babel-runtime предназначен для работы в паре с преобразованием - babel-plugin-transform-runtime, которое автоматически перепишет ваш код, чтобы вы могли написать свой код с использованием Promise API, и он будет преобразован для использования объекта, подобного Promise, экспортированного babel-runtime.

Так зачем использовать babel-polyfill против babel-runtime или наоборот? babel-polyfill предлагает вам возможности глобально определенных объектов без необходимости дальнейшего преобразования вашего кода. Однако, как и все, что изменяет глобальный объект, это может привести к конфликтам между версиями и т. Д.

babel-runtime, с другой стороны, не будет страдать от коллизий, так как все разделено по именам. Поскольку модуль будет определен в вашем package.json, для него можно будет управлять версиями, как и для всего остального. Компромисс, однако, заключается в том, что преобразование может сделать лишь очень многое. Среда выполнения переназначает методы в соответствии с картой определений. Как ни странно, это охватывало каждый из моих вариантов использования, но может быть один или два неясных метода, которые не переназначены. Также есть определенные случаи, когда ваше намерение как автора кода неоднозначно. В таких случаях преобразование не будет точно знать, что делать, поэтому вообще ничего не будет делать. Так обстоит дело, например, с методами экземпляра:

// this will not be transformed by babel-runtime because it's
// ambiguous. However, since babel-polyfill assigns methods directly
// on the String prototype, it will work:
"!!!".repeat(3)

Короче говоря, если вы пишете приложение, вам одинаково подойдут babel-polyfill или babel-runtime. Лично я предпочитаю среду выполнения, так как наш код уже транслируется с помощью babel, поэтому привязка к другому преобразованию не имеет значения, и нет возможности столкновения пространства имен или некоторого стороннего кода, делающего предположения на основе собственного плохо написанного полифилла. В любом случае их нужно будет рассматривать как зависимости вашего приложения, а с babel-runtime вам нужно будет включить babel-plugin-transform-runtime как , по крайней мере, зависимость от разработки (поскольку она должна быть доступна во время компиляции, но не во время выполнения).

Если вы пишете модуль, который хотите использовать в других проектах, никогда не используйте полифил. Поскольку вы не можете контролировать весь контекст, в котором вы будете выполнять, вы не можете гарантировать, что не будет нескольких версий различных полифиллов. Лучше перестраховаться и иметь пространство имен для всех ваших методов и объектов ES2015 с помощью babel-runtime.

2015–12–18, 19:50 EST: как указал Эрик Феррайуоло, будут случаи, когда вам вообще не понадобятся полифиллы. Если вы пишете библиотеку, в которой учитываются килобайты (например, в браузере), возможно, вам лучше избегать чрезмерного количества этих конкретных полифиллов все-в-одном. Простое документирование методов ES2015, на которые вы полагаетесь (как Facebook сделал для React), или добавление отдельных полифиллов приведет к значительно меньшей библиотеке.

Что это означает с практической точки зрения?

Подводя итог, в общем случае для Babel 6 необходимо выполнить два основных шага:

  • Предоставьте своему коду эмулированную среду ES2015, потребовав либо babel-polyfill, либо модуля babel-runtime плюс babel-plugin-transform-runtime преобразовать:
// for babel-polyfill, either add:
require('babel-polyfill');
// ... at the top of your root script, or, if on node >= 4,
// you can call your script with the --require flag to include it
// like so:
node --require babel-polyfill myApp.js
// for babel-runtime, install the module, then use the
// babel-plugin-transform-runtime transform by including it in
// your .babelrc file or declaring it when compiling:
babel --plugins transform-runtime myApp.js
  • Выполните серию преобразований своего кода с помощью babel cli (предоставляется babel-cli) или .transform api (предоставляется babel-core) или неявно, когда требуется (через babel-register)