Подключение кастомного babel.config.js

Parcel использует Babel как один из ключевых трансформеров JavaScript-кода. Его задача — преобразование современного ECMAScript в код, совместимый с целевыми окружениями, а также поддержка JSX, TypeScript-синтаксиса (в связке с TypeScript-трансформером), экспериментальных предложений языка и пользовательских плагинов.

Внутри пайплайна Parcel трансформация JavaScript проходит через несколько этапов: анализ модуля, применение нужного трансформера и генерация оптимизированного бандла. Babel подключается автоматически, если в проекте обнаруживаются соответствующие конфигурационные файлы или синтаксические конструкции, требующие трансляции.

Форматы конфигурации Babel

Babel поддерживает несколько форматов конфигурации:

  • babel.config.js — глобальная конфигурация уровня проекта или монорепозитория
  • .babelrc — локальная конфигурация, привязанная к директории
  • package.jsonbabel — inline-конфигурация

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

babel.config.js является наиболее универсальным вариантом, так как применяется ко всему графу зависимостей, включая внешние пакеты, если это не ограничено явно.

Подключение babel.config.js в Parcel

Parcel не требует ручного подключения Babel-конфигурации. Достаточно наличия файла babel.config.js в корне проекта.

Типовой сценарий:

project/
  src/
  index.js
  babel.config.js
  package.json

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

Важная особенность заключается в том, что Parcel не «импортирует» конфигурацию вручную, а считывает её через стандартный Babel API (@babel/core). Это означает, что любые изменения в конфигурации влияют на поведение трансформации без дополнительных шагов интеграции.

Поведение Parcel при обнаружении конфигурации

При старте сборки Parcel выполняет следующие действия:

  1. Обходит дерево зависимостей проекта

  2. Определяет тип каждого модуля

  3. Для JavaScript-файлов проверяет наличие Babel-конфигурации

  4. Если babel.config.js найден:

    • инициализирует Babel трансформер
    • применяет конфигурацию ко всем подходящим файлам
  5. Кэширует результат трансформации для ускорения повторных сборок

Важно, что babel.config.js имеет глобальный характер. Это означает, что он может влиять не только на код проекта, но и на зависимости в node_modules, если Parcel не исключает их явно через резолвер или настройки транспиляции.

Пример babel.config.js

Базовая конфигурация для современного проекта:

module.exports = function (api) {
  api.cache(true);

  return {
    presets: [
      [
        '@babel/preset-env',
        {
          targets: {
            browsers: ['last 2 versions', '> 1%']
          },
          modules: false
        }
      ],
      '@babel/preset-react'
    ],
    plugins: [
      '@babel/plugin-proposal-class-properties',
      '@babel/plugin-syntax-dynamic-import'
    ]
  };
};

Ключевая особенность — использование функции вместо объекта. Это позволяет включать кэширование через api.cache, что критично для Parcel, так как он активно использует файловый кэш между сборками.

Настройка пресетов и плагинов

Parcel не накладывает ограничений на состав Babel-конфигурации. Поддерживаются все стандартные пресеты и плагины.

Наиболее распространённые сценарии:

  • @babel/preset-env для управления совместимостью
  • @babel/preset-react для JSX
  • @babel/preset-typescript при работе с TS без отдельного компилятора
  • @babel/plugin-transform-runtime для уменьшения дублирования вспомогательных функций

Пример расширенной конфигурации:

module.exports = function (api) {
  api.cache(true);

  return {
    presets: [
      '@babel/preset-react',
      [
        '@babel/preset-env',
        {
          targets: {
            node: '16',
            browsers: ['defaults']
          },
          bugfixes: true
        }
      ]
    ],
    plugins: [
      '@babel/plugin-transform-runtime',
      '@babel/plugin-proposal-object-rest-spread',
      process.env.NODE_ENV === 'production' && 'babel-plugin-transform-remove-console'
    ].filter(Boolean)
  };
};

Parcel корректно обрабатывает условные плагины, если итоговый массив возвращается в валидной форме.

Различия .babelrc и babel.config.js в Parcel

Разница между двумя форматами становится критичной в крупных проектах.

.babelrc:

  • применяется локально к директории
  • не всегда распространяется на node_modules
  • может конфликтовать при вложенной структуре

babel.config.js:

  • глобальная область действия
  • единая точка конфигурации
  • лучше подходит для монорепозиториев
  • более предсказуем в Parcel-сборке

Parcel приоритетно использует babel.config.js, если он присутствует, так как он уменьшает количество неоднозначностей при построении dependency graph.

Монорепозитории

В монорепозиториях babel.config.js становится центральной точкой управления трансформацией всех пакетов.

Структура:

repo/
  babel.config.js
  packages/
    app/
    ui/
    shared/

Parcel при сборке каждого пакета поднимается вверх по дереву каталогов и обнаруживает корневую Babel-конфигурацию.

Типичный сценарий — использование overrides:

module.exports = function (api) {
  api.cache(true);

  return {
    presets: ['@babel/preset-env'],
    overrides: [
      {
        test: './packages/app',
        presets: ['@babel/preset-react']
      },
      {
        test: './packages/ui',
        presets: ['@babel/preset-typescript']
      }
    ]
  };
};

Такой подход позволяет централизованно управлять разными сборочными требованиями внутри одного Parcel-проекта.

Кэширование и пересборка

Parcel активно кэширует результаты Babel-трансформации. Изменение babel.config.js приводит к инвалидированию кэша, но только при корректном отслеживании зависимостей.

Особенности поведения:

  • изменение presets или plugins полностью инвалидирует JS-кэш
  • изменения в условиях NODE_ENV могут требовать перезапуска сборки
  • использование api.cache(true) ускоряет повторные сборки
  • динамические конфигурации могут снижать эффективность кэширования

При нестабильном кэшировании часто наблюдаются ситуации, когда старые трансформации продолжают применяться до очистки .parcel-cache.

Типичные проблемы и диагностика

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

Основные сценарии:

  • наличие нескольких Babel-конфигов в разных директориях
  • конфликт .babelrc и babel.config.js
  • исключение node_modules из трансформации Parcel
  • неверные test или ignore правила

Второй частый случай — плагины не работают из-за неправильного порядка:

  • пресеты должны идти до плагинов, изменяющих синтаксис
  • трансформирующие плагины должны учитывать уже преобразованный AST

Также встречаются проблемы с динамическими импортами:

  • отсутствие @babel/plugin-syntax-dynamic-import в старых конфигурациях
  • несовместимость с настройками preset-env без корректных targets

Диагностика обычно опирается на анализ итогового AST и логов Parcel в режиме verbose, где видно, какой трансформер применён к каждому модулю.