Общий .parcelrc для монорепозитория

В экосистеме Parcel файл .parcelrc является центральной точкой конфигурации пайплайна сборки. Через него определяется набор трансформеров, резолверов, валидаторов, упаковщиков (packagers), оптимизаторов и репортёров, которые используются при обработке исходного кода.

В монорепозиториях значение этого файла возрастает многократно. Вместо поддержки множества независимых конфигураций в каждом пакете создаётся единый стандарт сборки для всего репозитория. Это обеспечивает:

  • единообразное поведение сборщика;
  • централизованное управление зависимостями;
  • снижение дублирования настроек;
  • упрощение обновления инструментов;
  • предсказуемость процессов CI/CD.

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

repo/
├── .parcelrc
├── package.json
├── packages/
│   ├── ui/
│   ├── core/
│   ├── utils/
│   └── config/
├── applications/
│   ├── web/
│   └── admin/
└── node_modules/

В таком случае общий .parcelrc располагается в корне проекта и используется всеми приложениями и библиотеками внутри репозитория.


Стандартная конфигурация Parcel

По умолчанию Parcel использует встроенную конфигурацию:

{
  "extends": "@parcel/config-default"
}

Файл сообщает сборщику использовать стандартный набор плагинов.

Эквивалентный .parcelrc:

{
  "extends": "@parcel/config-default"
}

Даже если требуется всего несколько собственных настроек, рекомендуется наследовать стандартную конфигурацию вместо полного переопределения пайплайна.


Наследование конфигурации

Ключевым механизмом для крупных проектов является свойство extends.

Пример:

{
  "extends": "@parcel/config-default"
}

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

Также возможно наследование от собственного пакета:

{
  "extends": "@company/parcel-config"
}

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

Структура может выглядеть следующим образом:

packages/
└── parcel-config/
    ├── package.json
    └── .parcelrc

В результате обновление корпоративной конфигурации автоматически распространяется на все проекты.


Централизация трансформеров

Трансформеры отвечают за преобразование исходных файлов.

Например, общий .parcelrc может содержать:

{
  "extends": "@parcel/config-default",
  "transformers": {
    "*.svg": [
      "@parcel/transformer-svg-react"
    ]
  }
}

Теперь любой пакет внутри монорепозитория получает одинаковую обработку SVG-файлов.

Пример использования:

import Logo from './logo.svg';

export function Header() {
    return <Logo />;
}

Без единого .parcelrc каждому приложению пришлось бы отдельно настраивать поддержку SVG-компонентов.


Общие настройки TypeScript

Во многих монорепозиториях присутствует множество пакетов TypeScript.

Структура:

packages/
├── core/
├── api/
├── ui/
└── shared/

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

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

{
  "extends": "@parcel/config-default",
  "transformers": {
    "*.{ts,tsx}": [
      "@parcel/transformer-typescript-tsc"
    ]
  }
}

Это гарантирует одинаковую обработку файлов независимо от расположения пакета.


Настройка резолверов

Резолверы определяют способ поиска модулей.

В монорепозитории часто используются:

  • workspace-пакеты;
  • внутренние библиотеки;
  • алиасы;
  • виртуальные модули.

Пример:

{
  "extends": "@parcel/config-default",
  "resolvers": [
    "...",
    "@parcel/resolver-glob"
  ]
}

Символ "..." означает сохранение всех стандартных резолверов с добавлением нового.

Подобный подход предотвращает потерю встроенной функциональности Parcel.


Использование внутренних пакетов

Предположим, в репозитории имеются библиотеки:

packages/
├── ui
├── auth
└── analytics

Импорт может выглядеть так:

import { Button } from '@company/ui';
import { login } from '@company/auth';

Общий .parcelrc позволяет обеспечить одинаковую логику поиска внутренних модулей независимо от конкретного приложения.

Это особенно важно для:

  • Yarn Workspaces;
  • npm Workspaces;
  • pnpm Workspaces.

Общие валидаторы

Валидаторы выполняют проверку файлов до завершения сборки.

Пример:

{
  "extends": "@parcel/config-default",
  "validators": {
    "*.{ts,tsx}": [
      "@parcel/validator-typescript"
    ]
  }
}

После настройки каждый пакет автоматически получает одинаковые проверки.

Преимущества:

  • единый уровень качества кода;
  • отсутствие расхождений между пакетами;
  • раннее обнаружение ошибок.

Централизованные оптимизаторы

Оптимизаторы запускаются после формирования бандлов.

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

{
  "extends": "@parcel/config-default",
  "optimizers": {
    "*.js": [
      "@parcel/optimizer-terser"
    ]
  }
}

Теперь все приложения используют одинаковую стратегию минификации.

Особенно важно это для:

  • библиотек;
  • клиентских приложений;
  • серверного рендеринга;
  • микрофронтендов.

Настройка репортёров

Репортёры управляют выводом информации о сборке.

Пример:

{
  "extends": "@parcel/config-default",
  "reporters": [
    "...",
    "@parcel/reporter-bundle-analyzer"
  ]
}

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

Особенно полезно при анализе:

  • размера бандлов;
  • времени сборки;
  • состава зависимостей.

Собственные плагины внутри монорепозитория

Нередко организации создают собственные плагины Parcel.

Структура:

packages/
├── parcel-transformer-i18n/
├── parcel-reporter-ci/
└── parcel-validator-license/

После публикации во внутреннем workspace они могут подключаться централизованно:

{
  "extends": "@parcel/config-default",
  "transformers": {
    "*.json": [
      "@company/parcel-transformer-i18n"
    ]
  }
}

В результате вся инфраструктура сборки становится частью самого монорепозитория.


Расширение конфигурации отдельными пакетами

Иногда пакету требуются дополнительные настройки.

Корневой .parcelrc:

{
  "extends": "@parcel/config-default"
}

Локальный файл внутри приложения:

{
  "extends": "../. ./.parcelrc",
  "optimizers": {
    "*.js": [
      "@parcel/optimizer-terser"
    ]
  }
}

Parcel позволяет строить цепочки наследования.

Структура:

repo/
├── .parcelrc
└── applications/
    └── admin/
        └── .parcelrc

При таком подходе общие правила остаются централизованными, а специальные настройки ограничиваются конкретным проектом.


Корпоративный пакет конфигурации

В крупных организациях распространён следующий подход:

packages/
└── parcel-config/

Содержимое:

{
  "name": "@company/parcel-config",
  "version": "1.0.0"
}

Внутри:

{
  "extends": "@parcel/config-default",
  "transformers": {
    "*.svg": [
      "@parcel/transformer-svg-react"
    ]
  }
}

Использование:

{
  "extends": "@company/parcel-config"
}

Преимущества:

  • единый источник конфигурации;
  • независимое версионирование;
  • возможность переиспользования между репозиториями;
  • упрощённое сопровождение.

Организация зависимостей

Для общего .parcelrc желательно хранить связанные плагины на верхнем уровне монорепозитория.

Пример:

repo/
├── package.json
├── node_modules/
└── .parcelrc

Корневой package.json:

{
  "devDependencies": {
    "parcel": "^2.0.0",
    "@parcel/config-default": "^2.0.0",
    "@parcel/optimizer-terser": "^2.0.0",
    "@parcel/transformer-svg-react": "^2.0.0"
  }
}

Это исключает ситуацию, когда разные пакеты используют разные версии одного и того же плагина.


Типичные ошибки при настройке общего .parcelrc

Полное переопределение конфигурации

Неправильно:

{
  "transformers": {
    "*.svg": [
      "@parcel/transformer-svg-react"
    ]
  }
}

В этом случае стандартная конфигурация исчезает.

Правильно:

{
  "extends": "@parcel/config-default",
  "transformers": {
    "*.svg": [
      "@parcel/transformer-svg-react"
    ]
  }
}

Отсутствие оператора расширения массива

Неправильно:

{
  "reporters": [
    "@parcel/reporter-bundle-analyzer"
  ]
}

Стандартные репортёры будут удалены.

Правильно:

{
  "reporters": [
    "...",
    "@parcel/reporter-bundle-analyzer"
  ]
}

Разные версии плагинов

Проблемная структура:

packages/
├── app-a/
│   └── node_modules/
├── app-b/
│   └── node_modules/
└── app-c/
    └── node_modules/

Возможны ситуации, когда один пакет использует старую версию трансформера, а другой — новую.

Для монорепозиториев предпочтительно хранить плагины централизованно.


Рекомендуемая архитектура общего .parcelrc

Практическая структура:

{
  "extends": "@parcel/config-default",

  "resolvers": [
    "...",
    "@parcel/resolver-glob"
  ],

  "transformers": {
    "*.svg": [
      "@parcel/transformer-svg-react"
    ]
  },

  "validators": {
    "*.{ts,tsx}": [
      "@parcel/validator-typescript"
    ]
  },

  "reporters": [
    "...",
    "@parcel/reporter-bundle-analyzer"
  ]
}

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