Babel config js где находится
Перейти к содержимому

Babel config js где находится

  • автор:

Конфигурирование Babel

Babel автоматически конфигурируется для всех файлов .js и .jsx через babel-loader с благоразумными значениями по умолчанию (например, с @babel/preset-env и @babel/preset-react , по запросу).

Вам нужно ещё больше расширить конфигурацию Babel? Самый лёгкий способ сделать это — через configureBabel() :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// webpack.config.js // . Encore // . .configureBabel(function(babelConfig) < // добавить дополнительные пресеты babelConfig.presets.push('@babel/preset-flow'); // по умолчанию плагины не добавляются, но вы можете их добавить babelConfig.plugins.push('styled-jsx/babel'); >, < // node_modules не обрабатывается через Babel по умолчанию, // но вы можете позволить обработку каких-то конкретных модулей includeNodeModules: ['foundation-sites'], // или полностью контролировать правило исключения (заметьте, что вы не // можете использовать "includeNodeModules" и "exclude" одновременно) exclude: /bower_components/ >) ;

Конфигурация целей браузера

Пресет @babel/preset-env переписывает ваш JavaScript, чтобы финальный синтаксис работал в любом браузере, который вы захотите. Чтобы сконфигурировать браузеры, которые вам нужно поддерживать, см. PostCSS и автоматическое добавление префиксов (postcss-loader).

После изменения вашей конфигурации «browserslist», вам понадобится вручную удалить каталог кеша babel:

# В Unix запустите эту команду. В Windows, очистите этот каталог вручную $ rm -rf node_modules/.cache/babel-loader/

Создание файла .babelrc

Вместо того, чтобы вызывать configureBabel() , вы можете создать файл .babelrc в корне вашего проекта. Это более «стандартный» способ конфигурации Babel, но у него есть недостатки: как только появляется файл .babelrc , Encore больше не может добавлять никакую конфигурацию Babel для вас. Например, если вы вызовете Encore.enableReactPreset() , предустановка react не будет автоматически добавлена в Babel: вы должны будете добавить её сами в .babelrc .

Как только файл .babelrc будет существовать, он будет главенствовать над конфигурацией Babel, добавленной Encore.

Symfony is a trademark of Symfony SAS. Переклад — Playtini. UA RU RU EN

Configure Babel

Babel can be configured! Many other tools have similar configs: ESLint ( .eslintrc ), Prettier ( .prettierrc ).

All Babel API options are allowed. However, if the option requires JavaScript, you may want to use a JavaScript configuration file.

What’s your use case?​

  • You are using a monorepo?
  • You want to compile node_modules ?
  • You have a configuration that only applies to a single part of your project?
  • Guy Fieri is your hero?

babel.config.json ​

Create a file called babel.config.json with the following content at the root of your project (where the package.json is).

babel.config.json

  "presets": [. ],  "plugins": [. ] > 

Check out the babel.config.json documentation to see more configuration options.

.babelrc.json ​

Create a file called .babelrc.json with the following content in your project.

.babelrc.json

  "presets": [. ],  "plugins": [. ] > 

Check out the .babelrc documentation to see more configuration options.

package.json ​

Alternatively, you can choose to specify your .babelrc.json config from within package.json using the babel key like so:

package.json

  "name": "my-package",  "version": "1.0.0",  "babel":  "presets": [ . ],  "plugins": [ . ],  > > 

JavaScript configuration files​

You can also write babel.config.js (like we’re doing), and .babelrc.js files using JavaScript:

babel.config.js

module.exports = function (api)   api.cache(true);  const presets = [ . ]; const plugins = [ . ];  return   presets,  plugins >; > 

You are allowed to access any Node.js APIs, for example a dynamic configuration based on the process environment:

babel.config.js

module.exports = function (api)   api.cache(true);  const presets = [ . ]; const plugins = [ . ];  if (process.env["ENV"] === "prod")   plugins.push(. ); >  return   presets,  plugins >; > 

You can read more about JavaScript configuration files in the dedicated documentation

Using the CLI ( @babel/cli )​

babel --plugins @babel/plugin-transform-arrow-functions script.js 

Check out the babel-cli documentation to see more configuration options.

Using the API ( @babel/core )​

JavaScript

require("@babel/core").transformSync("code",   plugins: ["@babel/plugin-transform-arrow-functions"], >); 

Check out the babel-core documentation to see more configuration options.

Print effective configs​

You can tell Babel to print effective configs on a given input path

  • Shell
  • powershell
 # *nix or WSL BABEL_SHOW_CONFIG_FOR=./src/myComponent.jsx npm start 
  $env:BABEL_SHOW_CONFIG_FOR = ".srcmyComponent.jsx"; npm start 

BABEL_SHOW_CONFIG_FOR accepts both absolute and relative file paths. If it is a relative path, it will be resolved from cwd .

Once Babel processes the input file specified by BABEL_SHOW_CONFIG_FOR , Babel will print effective configs to the console. Here is an example output:

Babel configs on "/path/to/cwd/src/index.js" (ascending priority): config /path/to/cwd/babel.config.json   "sourceType": "script",  "plugins": [  "@foo/babel-plugin-1"  ],  "extends": "./my-extended.js" > config /path/to/cwd/babel.config.json .env["test"]   "plugins": [  [  "@foo/babel-plugin-3",    "noDocumentAll": true  >,  ]  ] > config /path/to/cwd/babel.config.json .overrides[0]   "test": "src/index.js",  "sourceMaps": true > config /path/to/cwd/.babelrc <> programmatic options from @babel/cli   "sourceFileName": "./src/index.js",  "presets": [  "@babel/preset-env"  ],  "configFile": "./my-config.js",  "caller":  "name": "@babel/cli"  >,  "filename": "./src/index.js" > 

Babel will print effective config sources ordered by ascending priority. Using the example above, the priority is:

babel.config.json < .babelrc < programmatic options from @babel/cli

In other words, babel.config.json is overwritten by .babelrc , and .babelrc is overwritten by programmatic options.

For each config source, Babel prints applicable config items (e.g. overrides and env ) in the order of ascending priority. Generally each config sources has at least one config item — the root content of configs. If you have configured overrides or env , Babel will not print them in the root, but will instead output a separate config item titled as .overrides[index] , where index is the position of the item. This helps determine whether the item is effective on the input and which configs it will override.

If your input is ignored by ignore or only , Babel will print that this file is ignored.

How Babel merges config items​

Babel’s configuration merging is relatively straightforward. Options will overwrite existing options when they are present and their value is not undefined . There are, however, a few special cases:

  • For assumptions , parserOpts and generatorOpts , objects are merged, rather than replaced.
  • For plugins and presets , they are replaced based on the identity of the plugin/preset object/function itself combined with the name of the entry.
Option (except plugin/preset) merging​

As an example, consider a config with:

JavaScript

  sourceType: "script", assumptions:   setClassFields: true, iterableIsArray: false >, env:   test:   sourceType: "module", assumptions:   iterableIsArray: true, >, > > >; 

When NODE_ENV is test , the sourceType option will be replaced and the assumptions option will be merged. The effective config is:

JavaScript

  sourceType: "module", // sourceType: "script" is overwritten assumptions:   setClassFields: true, iterableIsArray: true, // assumptions are merged by Object.assign >, > 
Plugin/Preset merging​

As an example, consider a config with:

JavaScript

plugins: [ './other', ['./plug',  thing: true, field1: true >] ], overrides: [  plugins: [ ['./plug',  thing: false, field2: true >], ] >] 

The overrides item will be merged on top of the top-level options. Importantly, the plugins array as a whole doesn’t just replace the top-level one. The merging logic will see that «./plug» is the same plugin in both cases, and < thing: false, field2: true >will replace the original options, resulting in a config as

JavaScript

plugins: [ './other', ['./plug',  thing: false, field2: true >], ], 

Since merging is based on identity + name, it is considered an error to use the same plugin with the same name twice in the same plugins / presets array. For example

JavaScript

plugins: ["./plug", "./plug"]; 

is considered an error, because it’s identical to plugins: [‘./plug’] . Additionally, even

JavaScript

plugins: [["./plug",  one: true >], ["./plug",  two: true >]]; 

is considered an error, because the second one would just always replace the first one.

If you actually do want to instantiate two separate instances of a plugin, you must assign each one a name to disambiguate them. For example:

JavaScript

plugins: [ ["./plug",  one: true >, "first-instance-name"], ["./plug",  two: true >, "second-instance-name"], ]; 

because each instance has been given a unique name and thus a unique identity.

Babel + core-js + IE = .

Сегодня будет рассказ про фронтендерский зоопарк. Начну издалека.

Если вы фронт, то вы знаете, что наш код читается многими браузерами. Вы также знаете, что разные браузеры реализуют разные части стандарта языка, а одинаковые части реализуют по-разному. Одно время такая разница в прочтении превращала разработку в ад. Но довольно быстро появились инструменты, “уравнивающие” ваш код таким образом, чтобы во всех браузерах он читался одинаково.

Мы во ВКонтакте местами поддерживаем IE 11, поэтому для нас вопрос кроссбраузерности стоит остро.

Полифиллы

В сети можно найти бесконечное количество полифиллов для почти всего, что придумано в стандарте: Array.prototype.map , Object.keys , Map , Promise , etc.

Полифилл — это кусочек рантайм-кода, который реализует недостающий функционал так, чтобы он во всех браузерах работал одинаково.

Представим, что у нас есть такой код:

const user = < first_name: 'John' >; const userExtended = Object.assign(<>, user, < last_name: 'Doe' >);

И нам не повезло так, что приходится поддерживать пользователей на IE.

Сейчас самая популярная библиотека полифиллов — это core-js . Чтобы использовать её, что называется, втупую, можно просто сделать импорт всего пакета в самом начале вашего модуля:

import 'core-js'; const user = < first_name: 'John' >; const userExtended = Object.assign(<>, user, < last_name: 'Doe' >);

core-js весит очень много, поэтому умнее будет импортнуть только то, что вы планируете использовать:

import 'core-js/actual/object/assign'; const user = < first_name: 'John' >; const userExtended = Object.assign(<>, user, < last_name: 'Doe' >); 

Вроде прикольно. Но далеко от совершенства.

Ваше приложение усложняется, команда растёт и в какой-то момент вы начинаете испытывать дискомфорт от того, что на ревью кто-то в очередной раз не заметил, что в код завезли новый модный метод массива, забыв дописать импорт полифилла. Итог — АНДЕЙФАЙНД ИЗ НОТ Э ФАНКШН.

Транспиляторы

Machines must suffer (c) Омар Хайям Андрей Ситник

Переложить заботу о стабильности кода на машины — отличная затея. Почти всегда. Почти. Babel — прекрасный инструмент. Он позволяет нам писать на современном стандарте языка, делая за нас все необходимые преобразования в ту версию, которую мы ему укажем.

Даже не так. Мы можем сказать бабелю: “мы поддерживаем вот такой набор браузеров, список найдёшь в .browserslistrc , всё, давай!”

Даже не так. Бабель сам посмотрит в этот файл, если он есть в корне проекта.

Причём в первую очередь бабель решает не задачу поиска полифилла для всяких модных методов. Его основная фича — ТРАНСПИЛЯЦИЯ кода. Это когда вы пишете ваш любимый < . user, last_name: 'Doe' >(оператор, появившийся в es2015), а эта хрень работает в IE 11, который вышел в 2013.

Как так получается? С помощью транспиляции. Всё, что нам нужно сделать — это поставить пару пакетиков:

yarn add @babel/cli @babel/core @babel/preset-env

И создать пару конфигов:

// .babelrc.js module.exports = < "presets": ["@babel/preset-env"] >
# .browserslist last 1 chrome version IE 11

Допустим, наш файл выглядит так:

// script.js const user = < first_name: 'John' >; const userExtended = < . user, last_name: 'Doe' >;

При запуске npx babel script.js в консоли мы увидим следующее:

"use strict"; function ownKeys(object, enumerableOnly) < var keys = Object.keys(object); if (Object.getOwnPropertySymbols) < var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) < return Object.getOwnPropertyDescriptor(object, sym).enumerable; >)), keys.push.apply(keys, symbols); > return keys; > function _objectSpread(target) < for (var i = 1; i < arguments.length; i++) < var source = null != arguments[i] ? arguments[i] : <>; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) < _defineProperty(target, key, source[key]); >) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) < Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); >); > return target; > function _defineProperty(obj, key, value) < if (key in obj) < Object.defineProperty(obj, key, < value: value, enumerable: true, configurable: true, writable: true >); > else < obj[key] = value; >return obj; > var user = < first_name: 'John' >; var userExtended = _objectSpread(_objectSpread(<>, user), <>, < last_name: 'Doe' >); 

То есть Babel понял, что в нашем списке поддерживаемых браузеров затесался отсталый, который не знает о таком операторе. Поэтому он его ТРАНСПИЛИРУЕТ. В транспилированном коде уже нет спреда, есть какой-то свой спред, собранный из говна из es5.

Ещё раз

Транспиляция — это преобразование одной синтаксической конструкции в другую на этапе билда кода.

Полифилл — кусочек рантайм-кода, который докидывает недостающие методы, функции, конструкторы и т.д.

С помощью полифилла нельзя сделать так, чтобы ?? завёлся в IE 11. Потому что это незнакомая синтаксическая конструкция, которую никаким рантайм-кодом не сделать интерпретируемой. Её можно только заменить на другую перед тем, как она попадёт в браузер. Этим и занимается Babel.

Как это работает?

Бабель состоит из плагинов и пресетов.

Каждый плагин отвечает за преобразование конкретной конструкции языка. Есть, например, плагин для преобразования JSX в React.createElement . Или преобразователь любимого всеми ?? в обычный тернарник.

Пресеты — это тупо набор плагинов, объединенных по какому-то признаку. Есть, например, пресет для реакта. Или для тайпскрипта.

Но самый прикольный пресет — это тот, который мы установили.

@babel/preset-env — это умный пресет, который подключает только те плагины, которые нужны, основываясь на браузерах, которые поддерживает конкретный проект. Собсно, для этого мы и положили файлик .browserslistrc рядом с .babelrc .

Давайте для эксперимента уберем IE 11 из браузерлиста и снова запустим бабель.

Смотрите, что получается:

"use strict"; const user = < first_name: 'John' >; const userExtended = < . user, last_name: 'Doe' >; 

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

Это знание получается из пакета caniuse-lite , который находится в зависимостях browserslist , который находится в зависимостях у @babel/preset-env .

Примечание @rock: @babel/preset-env берёт данные не из caniuse-lite, а из собственной базы @babel/compat-data

Круто? Я считаю, что круто.

Проблемы

С использованием современных конструкций языка вроде разобрались. Бабель будет решать проблему несовместимости за нас.

Но если мы напишем нечто такое:

const user = < first_name: 'John' >; const userExtended = < . user, last_name: 'Doe' >; console.log(Object.values(userExtended)); // внимание на эту строчку

и запустим бабель, то мы увидим, что Object.values остался нетронутым:

"use strict"; function ownKeys(object, enumerableOnly) < var keys = Object.keys(object); if (Object.getOwnPropertySymbols) < var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) < return Object.getOwnPropertyDescriptor(object, sym).enumerable; >)), keys.push.apply(keys, symbols); > return keys; > function _objectSpread(target) < for (var i = 1; i < arguments.length; i++) < var source = null != arguments[i] ? arguments[i] : <>; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) < _defineProperty(target, key, source[key]); >) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) < Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); >); > return target; > function _defineProperty(obj, key, value) < if (key in obj) < Object.defineProperty(obj, key, < value: value, enumerable: true, configurable: true, writable: true >); > else < obj[key] = value; >return obj; > var user = < first_name: 'John' >; var userExtended = _objectSpread(_objectSpread(<>, user), <>, < last_name: 'Doe' >); console.log(Object.values(userExtended)); // внимание на эту строчку 

Хотя этот метод появился в es2015 и IE 11 его не поддерживает. То есть этот код в IE упадёт с ошибкой! Как же нам быть?

Babel + core-js = ❤️

В @babel/preset-env есть решение этой проблемы. Давайте чутка подпилим наш конфиг:

// .babelrc.js module.exports = < "presets": [["@babel/preset-env", < "useBuiltIns": "usage", "corejs": 3 >]] >

Если переводить на русский, то написано следующее: “дорогой пресет энв, если ты в коде заметишь современные конструкции, которые можно заполифиллить, то так пожалуйста и сделай. Используй для этого core-js 3-й версии. Спасибо”

"use strict"; require("core-js/modules/es.object.keys.js"); require("core-js/modules/es.symbol.js"); require("core-js/modules/es.array.filter.js"); require("core-js/modules/es.object.to-string.js"); require("core-js/modules/es.object.get-own-property-descriptor.js"); require("core-js/modules/web.dom-collections.for-each.js"); require("core-js/modules/es.object.get-own-property-descriptors.js"); require("core-js/modules/es.object.values.js"); function ownKeys(object, enumerableOnly) < var keys = Object.keys(object); if (Object.getOwnPropertySymbols) < var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) < return Object.getOwnPropertyDescriptor(object, sym).enumerable; >)), keys.push.apply(keys, symbols); > return keys; > function _objectSpread(target) < for (var i = 1; i < arguments.length; i++) < var source = null != arguments[i] ? arguments[i] : <>; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) < _defineProperty(target, key, source[key]); >) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) < Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); >); > return target; > function _defineProperty(obj, key, value) < if (key in obj) < Object.defineProperty(obj, key, < value: value, enumerable: true, configurable: true, writable: true >); > else < obj[key] = value; >return obj; > var user = < first_name: 'John' >; var userExtended = _objectSpread(_objectSpread(<>, user), <>, < last_name: 'Doe' >); console.log(Object.values(userExtended)); 

Что за дьявольщина, спросите вы? Я вчера задавался тем же вопросом.

Но давайте успокоимся и хладнокровно посмотрим на то, что натворил бабель.

Мы видим, что теперь для Object.values был импортирован полифилл из core-js . То есть этот код будет работать.

Точнее так. Этот код будет работать, когда мы все эти реквайры соберем в один большой JS-файл. Об этом чуть позже.

Но какого чёрта он добавил столько казалось бы лишних полифиллов? Например, полифилл для Object.keys . Это метод из стандарта es5. На сайте caniuse.com написано, что IE 11 его поддерживает. Пресет сошёл с ума?

На самом деле нет.

Дело в том, что core-js , который мы присобачили к пресет энву, имеет собственный мап, в котором чётко описано, с каких версий та и или иная фича поддержана в браузере. И прикол в том, что хоть Object.keys и работает в IE, с точки зрения создателей core-js , он работает там неправильно. Об этом мне поведал мейнтенер бабеля.

То есть сам пресет энв берет инфу о поддержке той или иной конструкции из caniuse-lite , а core-js — из собственного мапа. Веселуха!

Измерения

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

yarn add babel-loader

Конфиг вебпака as simple as possible:

// webpack.config.js module.exports = < mode: 'production', entry: './src/index.js', module: < rules: [< test: /.js$/, exclude: /node_modules/, use: 'babel-loader' >] >, > 
// src/index.js const user = < first_name: 'John' >; const userExtended = < . user, last_name: 'Doe' >; console.log(Object.values(userExtended));

После минимизации такой код весит 64 байта. Запускаем npx webpack

Без автополифиллов

last 2 chrome versions last 2 safari versions last 2 opera versions last 2 edge versions last 2 firefox versions

То есть вебпак сделал x2, обмазав код своим бойлерплейтом. Терпимо.

last 2 chrome versions last 2 safari versions last 2 opera versions last 2 edge versions last 2 firefox versions IE 11

Желание поддерживать IE 11 увеличивает размер бандла в 10 раз. Стерпим и это.

С автополифиллами

last 2 chrome versions last 2 safari versions last 2 opera versions last 2 edge versions last 2 firefox versions

134 bytes. Логично, так как все перечисленные браузеры ни в каких полифиллах не нуждаются.

last 2 chrome versions last 2 safari versions last 2 opera versions last 2 edge versions last 2 firefox versions IE 11 
defaults

22.7 KiB (x170). Ну вы поняли. Самая мерзость в том, что даже дефолтные настройки браузерлиста генерят такой огромный кусок JS.

Визуализация

Результат выполнения команды npx webpack --analyze

Наш index.js (справа) весит 2 KB, а полифиллы для него — больше 20. И всё ради одного браузера.

Итоги

  • При использовании @babel/preset-env обязательно позаботьтесь о том, чтобы указать список интересующих лично вас браузеров. Иначе ваши пользователи будут скачивать огромную кучу скорее всего ненужного кода.
  • В топку IE.

Config Files

Babel has two parallel config file formats, which can be used together, or independently.

Version Changes
v7.21.0 Support .babelrc.cts and babel.config.cts (Experimental)
v7.8.0 Support .babelrc.mjs and babel.config.mjs
v7.7.0 Support .babelrc.json , .babelrc.cjs , babel.config.json , babel.config.cjs
  • Project-wide configuration
    • babel.config.* files, with the following extensions: .json , .js , .cjs , .mjs , .cts .
    • .babelrc.* files, with the following extensions: .json , .js , .cjs , .mjs , .cts .
    • .babelrc file, with no extension.
    • package.json files, with a «babel» key.

    Project-wide configuration​

    New in Babel 7.x, Babel has a concept of a «root» directory, which defaults to the current working directory. For project-wide configuration, Babel will automatically search for a babel.config.json file, or an equivalent one using the supported extensions, in this root directory. Alternatively, users can use an explicit «configFile» value to override the default config file search behavior.

    Because project-wide config files are separated from the physical location of the config file, they can be ideal for configuration that must apply broadly, even allowing plugins and presets to easily apply to files in node_modules or in symlinked packages, which were traditionally quite painful to configure in Babel 6.x.

    The primary downside of this project-wide config is that, because it relies on the working directory, it can be more painful to use in monorepos if the working directory is not the monorepo root. See the monorepo documentation for examples of how to use config files in that context.

    Project-wide configs can also be disabled by setting «configFile» to false .

    File-relative configuration​

    Babel loads .babelrc.json files, or an equivalent one using the supported extensions, by searching up the directory structure starting from the «filename» being compiled (limited by the caveats below). This can be powerful because it allows you to create independent configurations for subsections of a package. File-relative configurations are also merged over top of project-wide config values, making them potentially useful for specific overrides, though that can also be accomplished through «overrides».

    There are a few edge cases to consider when using a file-relative config:

    • Searching will stop once a directory containing a package.json is found, so a relative config only applies within a single package.
    • The «filename» being compiled must be inside of «babelrcRoots» packages, or else searching will be skipped entirely.

    These caveats mean that:

    • .babelrc.json files only apply to files within their own package
    • .babelrc.json files in packages that aren’t Babel’s ‘root’ are ignored unless you opt in with «babelrcRoots».

    See the monorepo documentation for more discussion on how to configure monorepos that have many packages. File-relative configs can also be disabled by setting «babelrc» to false .

    6.x vs 7.x .babelrc loading​

    Users coming from Babel 6.x will likely trip up on these two edge cases, which are new in Babel 7.x. These two restrictions were added to address common footguns in Babel 6.x:

    • .babelrc files applied to node_modules dependencies, often unexpectedly.
    • .babelrc files failed to apply to symlinked node_modules when people expected them to behave like normal dependencies.
    • .babelrc files in node_modules dependencies would be detected, even though the plugins and presets inside they were generally not installed, and may not even be valid in the version of Babel compiling the file.

    These cases will primarily cause issues for users with a monorepo structure, because if you have

    .babelrc packages/  mod1/  package.json  src/index.js  mod2/  package.json  src/index.js 

    the config will now be entirely ignored, because it is across a package boundary.

    One alternative would be to create a .babelrc in each sub-package that uses «extends» as

    .babelrc.json

    Unfortunately, this approach can be a bit repetitive, and depending on how Babel is being used, could require setting «babelrcRoots».

    Given that, it may be more desirable to rename the .babelrc to be a project-wide «babel.config.json». As mentioned in the project-wide section above, this may then require explicitly setting «configFile» since Babel will not find the config file if the working directory isn’t correct.

    Supported file extensions​

    Babel can be configured using any file extension natively supported by Node.js, as mentioned in Configuration File Types section:

    • babel.config.json and .babelrc.json are parsed as JSON5 and should contain an object matching the options format that Babel accepts. They have been supported since v7.7.0 . We recommend using this file type wherever possible: JS config files are handy if you have complex configuration that is conditional or otherwise computed at build time. However, the downside is that JS configs are less statically analyzable, and therefore have negative effects on cacheability, linting, IDE autocomplete, etc. Since babel.config.json and .babelrc.json are static JSON files, it allows other tools that use Babel such as bundlers to cache the results of Babel safely, which can be a huge build performance win.
    • babel.config.cjs and .babelrc.cjs allow you to define your configuration as CommonJS, using module.exports . They have been supported since v7.7.0 .
    • babel.config.mjs and .babelrc.mjs use native ECMAScript modules. They are supported by Node.js 13.2+ (or older versions via the —experimental-modules flag). Please remember that native ECMAScript modules are asynchronous (that’s why import() always returns a promise!): for this reason, .mjs config files will throw when calling Babel synchronously. They have been supported since v7.8.0 .
    • babel.config.js and .babelrc.js behave like the .mjs equivalents when your package.json file contains the «type»: «module» option, otherwise they are exactly the same as the .cjs files.
    • babel.config.cts and .babelrc.cts allow you to define your configuration as Typescript + CommonJS. You must either install @babel/preset-typescript , or run Babel using ts-node .

    �� This functionality is experimental. It’s not possible yet to use babel.config.ts and babel.config.mts files, pending stabilization of the Node.js ESM loader API.

    JavaScript configuration files can either export an object, or a function that when called will return the generated configuration. Function-returning configs are given a few special powers because they can access an API exposed by Babel itself. See Config Function API for more information.

    For compatibility reasons, .babelrc is an alias for .babelrc.json .

    Monorepos​

    Monorepo-structured repositories usually contain many packages, which means that they frequently run into the caveats mentioned in file-relative configuration and config file loading in general. This section is aimed at helping users understand how to approach monorepo configuration.

    With monorepo setups, the core thing to understand is that Babel treats your working directory as its logical «root», which causes problems if you want to run Babel tools within a specific sub-package without having Babel apply to the repo as a whole.

    Separately, it is also important to decide if you want to use .babelrc.json files or just a central babel.config.json . .babelrc.json files are not required for subfolder-specific configuration like they were in Babel 6, so often they are not needed in Babel 7, in favor of babel.config.json .

    Root babel.config.json file​

    The first step in any monorepo structure should be to create a babel.config.json file in repository root. This establishes Babel’s core concept of the base directory of your repository. Even if you want to use .babelrc.json files to configure each separate package, it is important to have as a place for repo-level options.

    You can often place all of your repo configuration in the root babel.config.json . With «overrides», you can easily specify configuration that only applies to certain subfolders of your repository, which can often be easier to follow than creating many .babelrc.json files across the repo.

    The first issue you’ll likely run into is that by default, Babel expects to load babel.config.json files from the directory set as its «root», which means that if you create a babel.config.json , but run Babel inside an individual package, e.g.

    cd packages/some-package; babel src -d dist 

    the «root» Babel is using in that context is not your monorepo root, and it won’t be able to find the babel.config.json file.

    If all of your build scripts run relative to your repository root, things should already work, but if you are running your Babel compilation process from within a subpackage, you need to tell Babel where to look for the config. There are a few ways to do that, but the recommended way is the «rootMode» option with «upward» , which will make Babel search from the working directory upward looking for your babel.config.json file, and will use its location as the «root» value.

    One helpful way to test if your config is being detected is to place a console.log() call inside of it if it is a babel.config.json JavaScript file: the log will execute the first time Babel loads it.

    How you set this value varies by project, but here are a few examples:

    CLI​
    babel --root-mode upward src -d lib 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *