Babel -- транспиляция

Babel — JavaScript-компилятор, превращающий современный код (ES2020+, JSX, TypeScript) в более старый синтаксис, понятный целевым браузерам.

Зачем нужно

Браузеры и Node.js поддерживают разные версии JavaScript. Babel позволяет писать на новейшем синтаксисе (optional chaining, nullish coalescing, async/await, декораторы), не думая о совместимости: он автоматически преобразует код под нужные targets. Без Babel большинство современных фреймворков (React, Vue, Angular) не работали бы в старых браузерах.

Где используется

  • React-проекты: транспиляция JSX → React.createElement
  • Webpack/Vite/Rollup: как loader/plugin в цепочке сборки
  • Jest: трансформация тестового кода перед выполнением
  • Библиотеки: публикация в npm с поддержкой CJS и ESM одновременно
  • TypeScript-проекты (как альтернатива tsc для транспиляции без проверки типов)

Основной контент

Принцип работы

Исходный код → [Parser] → AST → [Transform Plugins] → AST → [Generator] → Выходной код

Три стадии: parse (код в AST), transform (плагины меняют AST), generate (AST обратно в код).

Установка

npm install --save-dev @babel/core @babel/cli @babel/preset-env

Конфигурация (babel.config.json)

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": "> 0.25%, not dead",
        "useBuiltIns": "usage",
        "corejs": 3
      }
    ]
  ],
  "plugins": 
}

Что делает @babel/preset-env

// Исходный код (ES2020)
const result = user?.profile?.name ?? 'Anonymous';
const doubled = [1, 2, 3].map(x => x * 2);

// После транспиляции (ES5-совместимый)
var _user, _user$profile;
var result = (_user = user) === null || _user === void 0
  ? void 0
  : (_user$profile = _user.profile) === null || _user$profile === void 0
  ? void 0
  : _user$profile.name;
result = result !== null && result !== void 0 ? result : 'Anonymous';

var doubled = [1, 2, 3].map(function(x) { return x * 2; });

Preset для React (JSX)

npm install --save-dev @babel/preset-react
{
  "presets": ["@babel/preset-env", "@babel/preset-react"]
}
// JSX → JS
const el = <div className="box">Hello</div>;
// ↓
const el = React.createElement("div", { className: "box" }, "Hello");

Интеграция с Webpack

npm install --save-dev babel-loader
// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: { loader: 'babel-loader' }
      }
    ]
  }
};

Частые ошибки

  • Нет @babel/runtime с useBuiltIns: "usage" — polyfill-код дублируется в каждом файле; нужен @babel/plugin-transform-runtime
  • Транспилируется node_modules — медленная сборка; всегда добавляй exclude: /node_modules/
  • Конфликт Babel и TypeScript — Babel стриппит типы, но не проверяет их; для проверки типов нужен отдельный tsc --noEmit
  • Устаревший .babelrc + babel.config.json — два файла конфигурации одновременно могут конфликтовать; используй один

Связанные темы

Ресурсы