Название вечеринка хахаха ~~~
Я считаю, что многие люди такие же, как и автор раньше.Конфигурация babel копируется и вставляется из Интернета или с помощью готовых скаффолдов.Хотя это работает, я надеюсь, что все могут знать, почему.Поэтому в этой статье будет делаться конфигурация о babel (babel@7) Более полный обзор.
синтаксис и API
Контент, добавленный es6, можно разделить на две части: грамматика и API, это очень важно понимать Новые грамматики, такие как стрелочные функции, деструктурирование и т. д.:
const fn = () => {}
const arr2 = [...arr1]
Новые API, такие как Map, Promise и т. д.:
const m = new Map()
const p = new Promise(() => {})
@babel/core
@ Babel / Core, вы можете увидеть из названия, что это ядро Бабела, без него, поэтому установите этот пакет первым
npm install @babel/core
Его роль заключается в преобразовании кода в соответствии с нашим конфигурационным файлом, который обычно.babelrc
(статические файлы) илиbabel.config.js
(программируемый), здесь с.babelrc
Например, создайте пустой файл в корневом каталоге проекта с именем.babelrc
, а затем создайте файл js (test.js) для тестирования:
/* test.js */
const fn = () => {}
Здесь мы устанавливаем@babel/cli
чтобы иметь возможность использовать babel из командной строки
npm install @babel/cli
После завершения установки выполните компиляцию babel и войдите в командную строку.
npx babel test.js --watch --out-file test-compiled.js
Оказалось, что содержимое test-compiled.js по-прежнему является стрелочной функцией es6.Не волнуйтесь, наш .babelrc еще не написал конфигурацию.
Плагины и пресеты
Now, out of the box Babel doesn't do anything. It basically acts like const babel = code => code; by parsing the code and then generating the same code back out again. You will need to add plugins for Babel to do anything.
Выше это отрывок с официального сайта Babel.Можно понять,что Babel основан на архитектуре плагинов.Если вы не предоставите никаких плагинов,то Babel не будет ничего делать,то есть то,что вы вводите и выводите еще что. Итак, теперь нам просто нужно предоставить плагин функции стрелки, если мы хотим преобразовать функцию обрезки в функцию es5:
/* .babelrc */
{
"plugins": ["@babel/plugin-transform-arrow-functions"]
}
Преобразованный test-compiled.js:
/* test.js */
const fn = () => {}
/* test-compiled.js */
const fn = function () {}
Так что, если я хочу использовать синтаксис деструктурирования es6? Это очень просто, просто добавьте плагин деструктуризации:
/* .babelrc */
{
"plugins": [
"@babel/plugin-transform-arrow-functions",
"@babel/plugin-transform-destructuring"
]
}
Проблема в том, что существуют так много грамматиков, которые необходимо преобразовать, и это слишком хлопотно, чтобы добавить плагины один за другим. К счастью, Babel предоставляетpresets
, его можно понимать как набор плагинов, что избавляет нас от необходимости вводить плагины один за другим. Официальный предоставляет множество пресетов, таких какpreset-env
(набор плагинов, которые обрабатывают синтаксис спецификации ES6+),preset-stage
(обработка коллекций плагинов, которые все еще находятся в синтаксисе предложения),preset-react
(набор плагинов, которые имеют дело с синтаксисом реакции) и т. д., здесь мы в основном представляем следующиеpreset-env
:
/* .babelrc */
{
"presets": ["@babel/preset-env"]
}
preset-env
@babel/preset-env is a smart preset that allows you to use the latest JavaScript without needing to micromanage which syntax transforms (and optionally, browser polyfills) are needed by your target environment(s).
Вышеупомянутый официальный сайт babelpreset-env
введение, примерно означает, чтоpreset-env
Он позволяет использовать синтаксис es6 для написания кода и преобразовывать только тот код, который необходимо преобразовать. по умолчаниюpreset-env
Ничего настраивать не нужно.В настоящее время он преобразует весь код es6+, но мы можем предоставить элемент конфигурации target для указания рабочей среды:
/* .babelrc */
{
"presets": [
["@babel/preset-env", {
"targets": "ie >= 8"
}]
]
}
На данный момент будут преобразованы только синтаксисы, которые не поддерживаются браузерами выше ie8.Глядя на наш файл test-compiled.js, все в порядке:
/* test.js */
const fn = () => {}
const arr1 = [1, 2, 3]
const arr2 = [...arr1]
/* test-compiled.js */
var fn = function fn() {};
var arr1 = [1, 2, 3];
var arr2 = [].concat(arr1);
@babel/polyfill
Теперь давайте немного изменим test.js:
/* test.js */
const fn = () => {}
new Promise(() => {})
/* test-compiled.js */
var fn = function fn() {};
new Promise(function () {});
Мы обнаружили, что обещания не обращаются, что! IE8 также поддерживает обещания? Это невозможно.... Помните, что содержание, добавленное к спецификации ES6 + в начале этой статьи, включает новые грамматики и новые API. Новые грамматики могут быть преобразованы с Babel, но новые API могут быть проведены только в полифах, поэтому нам нужно только установить их@babel/polyfill
, Затем следуют простые модификации test.js:
/* test.js */
import '@babel/polyfill'
const fn = () => {}
new Promise(() => {})
/* test-compiled.js */
import '@babel/polyfill';
var fn = function fn() {};
new Promise(function () {});
Теперь код может отлично работать в среде ie8, но все еще есть проблема:@babel/polyfill
Размер этого пакета слишком велик, нам нужен только Promise, если мы сможем полифилить его по мере необходимости. Какое совпадение,preset-env
Просто предоставил эту функцию:
/* .babelrc */
{
"presets": [
["@babel/preset-env", {
"modules": false,
"useBuiltIns": "entry",
"targets": "ie >= 8"
}]
]
}
мы просто даемpreset-env
добавить одинuseBuiltIns
Элементы конфигурации могут быть, значение может бытьentry
а такжеusage
, если этоentry
, добавит в запись полифиллы, которые все браузеры выше ie8 и выше не поддерживают API, а именно:
/* test.js */
import '@babel/polyfill'
const fn = () => {}
new Promise(() => {})
/* test-compiled.js */
import "core-js/modules/es6.array.copy-within";
import "core-js/modules/es6.array.every";
import "core-js/modules/es6.array.fill";
... //省略若干引入
import "core-js/modules/web.immediate";
import "core-js/modules/web.dom.iterable";
import "regenerator-runtime/runtime";
var fn = function fn() {};
new Promise(function () {});
Осторожно, вы обнаружите, что после преобразованияimport '@babel/polyfill'
Ушел, но куча большеimport 'core-js/...'
Содержание, на самом деле,@babel/polyfill
Сам пакет без содержимого, это зависит отcore-js
а такжеregenerator-runtime
Эти два пакета, эти два пакета обеспечивают среду выполнения спецификации ES6+. Поэтому, когда нам не нужны полифиллы по запросу, импортируйте их напрямую.@babel-polyfill
На линии, это будетcore-js
а такжеregenerator-runtime
Все импортное, когда нам нужно полифилить по требованию, нам нужно только настроитьuseBuiltIns
Вот и все, оно будет автоматически импортировать на спрос на основе целевой средыcore-js
а такжеregenerator-runtime
.
упомянутый ранееuseBuiltIns
Значение также может бытьusage
, его функция более мощная, он будет сканировать ваш код, только какой новый API использует ваш код, он представит соответствующий полифилл:
/* .babelrc */
{
"presets": [
["@babel/preset-env", {
"modules": false,
"useBuiltIns": "usage",
"targets": "ie >= 8"
}]
]
}
Преобразованный test-compiled.js будет соответственно сильно упрощен:
/* test.js */
const fn = () => {}
new Promise(() => {})
/* test-compiled.js */
import "core-js/modules/es6.promise";
import "core-js/modules/es6.object.to-string";
var fn = function fn() {};
new Promise(function () {});
К сожалению, эта функция все еще является экспериментальной, поэтому используйте ее с осторожностью.
На самом деле, если вы пишете приложение, приведенной выше конфигурации для babel почти достаточно, вам может понадобиться добавить какую-то конкретную цель.Plugin
а такжеPreset
, например, в реактивном проекте вам нужноpresets
Добавить к@babel/preset-react
, если вы хотите использовать функцию динамического импорта, вам нужноplugins
Добавить к@babel/plugin-syntax-dynamic-import
Подождите, они не повторяются. Если вы пишете публичную библиотеку или фреймворк, упомянутые ниже моменты также могут потребовать вашего внимания.
@babel/runtime
Иногда преобразование синтаксиса относительно сложно, и могут потребоваться некоторые вспомогательные функции, такие как преобразование классов es6:
/* test.js */
class Test {}
/* test-compiled.js */
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Test = function Test() {
_classCallCheck(this, Test);
};
В примере классу es6 нужна вспомогательная функция _classCallCheck.Представьте, что если мы используем класс es6 в нескольких файлах, то в каждом файле нужно снова определить функцию _classCallCheck, что также является большим расточительством.Извлечение вспомогательных функций в package, на который ссылаются все файлы, может значительно сократить объем кода. а также@babel/runtime
Он делает именно это, он предоставляет различные вспомогательные функции, но как мы узнаем, какую вспомогательную функцию вводить? Вы не можете импортировать его вручную.@babel/plugin-transform-runtime
Плагины помогают нам автоматически вводить помощников. Сначала мы устанавливаем@babel/runtime
а также@babel/plugin-transform-runtime
:
npm install @babel/runtime @babel/plugin-transform-runtime
Затем измените конфигурацию babel следующим образом:
/* .babelrc */
{
"presets": [
["@babel/preset-env", {
"modules": false,
"useBuiltIns": "usage",
"targets": "ie >= 8"
}]
],
"plugins": [
"@babel/plugin-transform-runtime"
]
}
Теперь посмотрим на файл test-compiled.js, вспомогательная функция _classCallCheck в нем уже из@babel/runtime
Представлено:
/* test.js */
class Test {}
/* test-compiled.js */
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
var Test = function Test() {
_classCallCheck(this, Test);
};
Увидев это, вы можете сказать, что это не чепуха! Сколько объема могут мне сэкономить несколько вспомогательных функций, прежде чем я поленюсь устанавливать плагины. Фактически@babel/plugin-transform-runtime
Есть еще одна важная функция, которая создаетsandboxed environment
(среда песочницы), что особенно важно, когда вы пишете обычный код, например библиотеки классов.
Как упоминалось выше, для Promise, Map и других стандартных API es6+ мы предоставляем полифиллы для совместимости с браузерами более ранних версий. Это будет иметь побочный эффект в виде загрязнения глобальных переменных. Если вы пишете приложение, это нормально. Но если вы пишете общедоступную библиотеку классов, это может вызвать некоторые проблемы, ваша библиотека классов может перезаписать некоторые глобальные API. к счастью@babel/plugin-transform-runtime
предоставляет нам элемент конфигурацииcorejs
, который изолирует эти переменные в локальной области видимости:
/* .babelrc */
{
"presets": [
["@babel/preset-env", {
"modules": false,
"targets": "ie >= 8"
}]
],
"plugins": [
["@babel/plugin-transform-runtime", {
"corejs": 2
}]
]
}
Примечание. Вы должны настроить COREDJS здесь и установить его одновременно@babel/runtime-corejs2
, без настройки@babel/plugin-transform-runtime
По умолчанию помощники для этих полифилов не вводятся. На данном этапе значение corejs обычно указывается равным 2, что приблизительно можно понимать как да.@babel/runtime
версия. Давайте теперь посмотрим, во что был преобразован test-compiled.js:
/* test.js */
class Test {}
new Promise(() => {})
/* test-compiled.js */
import _Promise from "@babel/runtime-corejs2/core-js/promise";
import _classCallCheck from "@babel/runtime-corejs2/helpers/classCallCheck";
var Test = function Test() {
_classCallCheck(this, Test);
};
new _Promise(function () {});
Как мы и хотели, для полифилла Promise создана среда песочницы.
Наконец, добавим кое-что в test.js:
/* test.js */
class Test {}
new Promise(() => {})
const b = [1, 2, 3].includes(1)
/* test-compiled.js */
import _Promise from "@babel/runtime-corejs2/core-js/promise";
import _classCallCheck from "@babel/runtime-corejs2/helpers/classCallCheck";
var Test = function Test() {
_classCallCheck(this, Test);
};
new _Promise(function () {});
var b = [1, 2, 3].includes(1);
Его можно найти,includes
方法并没有引入辅助函数,可这明明也是es6里面的api啊。 Это потому чтоincludes
Это метод экземпляра массива, который необходимо изменить, чтобы выполнить полифилл.Array
, который загрязняет глобальную окружающую среду, поэтому@babel/plugin-transform-runtime
Он не может обрабатывать методы экземпляра этих спецификаций es6+.
tips
Вышеизложенное в основном представляет собой все содержание этой статьи и, наконец, краткое изложение и моменты, на которые следует обратить внимание:
- В этой статье не упоминается
preset-stage
, фактически, Babel@7 устарел от его использования.Если вам нужно использовать синтаксис, который все еще предлагается, пожалуйста, добавьте соответствующий плагин напрямую. - Для обычных проектов вы можете напрямую использовать
preset-env
Настроить полифиллы - Для проектов библиотеки классов рекомендуется использовать
@babel/runtime
, вам нужно обратить внимание на использование некоторых методов экземпляра - Содержание этой статьи основано на babel@ 7. Если у вас возникнут проблемы в проекте, вы можете попробовать его обновить.
babel-loader
версия ...Быть добавленным
полный текст