Babel — это транспилятор JavaScript, предназначенный для преобразования современного синтаксиса ECMAScript в код, совместимый со старыми браузерами и средами выполнения. В большинстве сборщиков настройка Babel требует отдельной конфигурации, установки загрузчиков и интеграции в процесс сборки. Parcel реализует иной подход: Babel интегрирован в систему сборки и может работать практически без дополнительной настройки.
Основная идея заключается в автоматическом определении необходимости трансформации кода на основании целевых платформ проекта. Если используются современные возможности языка, Parcel способен самостоятельно подключить Babel и выполнить преобразование исходного кода.
Одним из преимуществ Parcel является концепция zero-configuration. После установки Parcel поддержка Babel уже присутствует внутри экосистемы сборщика.
Простейшая структура проекта может выглядеть следующим образом:
project/
├── src/
│ ├── index.js
│ └── app.js
├── package.json
└── .parcelrc
Файл JavaScript может использовать современный синтаксис:
const getUser = async () => {
const response = await fetch('/api/user');
return response.json();
};
getUser().then(user => console.log(user));
Во время сборки Parcel анализирует окружение и при необходимости преобразует конструкции:
Трансформация кода зависит от списка поддерживаемых браузеров. Parcel
получает эту информацию из поля browserslist.
Пример:
{
"browserslist": [
"> 0.5%",
"last 2 versions",
"not dead"
]
}
Либо:
{
"targets": {
"default": {
"engines": {
"browsers": [
"> 0.5%",
"last 2 versions"
]
}
}
}
}
На основе указанных целей Parcel автоматически определяет:
Чем современнее список целевых браузеров, тем меньше преобразований будет выполнять Babel.
Исходный код:
const sum = (a, b) => a + b;
После транспиляции для старых браузеров:
var sum = function(a, b) {
return a + b;
};
Исходный код:
class User {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(this.name);
}
}
После преобразования Babel генерирует более объемный ES5-код с использованием функций-конструкторов и вспомогательных методов.
Современный синтаксис:
const city = user?.address?.city;
После трансформации:
var city =
user == null
? void 0
: user.address == null
? void 0
: user.address.city;
Исходный код:
const count = value ?? 0;
После обработки:
var count = value !== null && value !== undefined
? value
: 0;
Несмотря на автоматическую работу, Parcel позволяет использовать полноценную конфигурацию Babel.
Для этого создается файл:
.babelrc
или
babel.config.json
Пример:
{
"presets": [
"@babel/preset-env"
]
}
После появления конфигурации Parcel начинает использовать настройки разработчика вместо встроенных параметров.
Если проект использует собственную конфигурацию, обычно требуется установить необходимые зависимости:
npm install --save-dev @babel/core
npm install --save-dev @babel/preset-env
Либо одной командой:
npm install --save-dev @babel/core @babel/preset-env
Конфигурация:
{
"presets": [
"@babel/preset-env"
]
}
Теперь управление трансформациями осуществляется через стандартные механизмы Babel.
Наиболее часто используемый пресет.
Пример:
{
"presets": [
"@babel/preset-env"
]
}
Он автоматически определяет необходимые преобразования в зависимости от списка поддерживаемых браузеров.
Можно явно указать целевые платформы:
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"chrome": "90",
"firefox": "88"
}
}
]
]
}
В таком случае Babel будет учитывать именно эти версии браузеров.
Babel поддерживает огромную экосистему плагинов.
Пример подключения:
{
"plugins": [
"@babel/plugin-transform-runtime"
]
}
Установка:
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
Плагин уменьшает дублирование вспомогательного кода, генерируемого Babel.
Некоторые возможности языка находятся на стадии разработки и не входят в стабильный стандарт ECMAScript.
Для их поддержки используются отдельные плагины.
Пример для декораторов:
npm install --save-dev @babel/plugin-proposal-decorators
Конфигурация:
{
"plugins": [
[
"@babel/plugin-proposal-decorators",
{
"version": "2023-11"
}
]
]
}
После этого становится доступен экспериментальный синтаксис:
@sealed
class User {
}
Parcel умеет работать с TypeScript без отдельной настройки Babel.
Пример файла:
interface User {
name: string;
}
const user: User = {
name: 'Alex'
};
Parcel автоматически удаляет типы во время сборки.
Однако при необходимости использования специфических возможностей Babel можно добавить соответствующие пресеты:
npm install --save-dev @babel/preset-typescript
Конфигурация:
{
"presets": [
"@babel/preset-typescript"
]
}
Для React-проектов Babel часто применяется для преобразования JSX.
Компонент:
function App() {
return <h1>Hello Parcel</h1>;
}
Установка:
npm install --save-dev @babel/preset-react
Конфигурация:
{
"presets": [
"@babel/preset-react"
]
}
После транспиляции JSX преобразуется в вызовы функций React.
Современные версии Parcel умеют определять React-проекты автоматически.
Файл:
import React from 'react';
export default function App() {
return <h1>Application</h1>;
}
При наличии соответствующих зависимостей Parcel подключает необходимые трансформации без ручной настройки Babel.
Транспиляция и полифилы — разные задачи.
Транспиляция изменяет синтаксис:
const fn = () => {};
↓
var fn = function() {};
Полифилы добавляют отсутствующие возможности среды выполнения.
Например:
Promise.allSettled([
promise1,
promise2
]);
Если браузер не поддерживает Promise.allSettled, одного
преобразования синтаксиса недостаточно.
Для автоматического подключения полифилов часто применяется
библиотека core-js.
Установка:
npm install core-js
Настройка:
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3
}
]
]
}
В режиме usage Babel анализирует исходный код и
подключает только необходимые полифилы.
Parcel реализует несколько механизмов оптимизации:
Результаты транспиляции сохраняются в кэш.
Повторная сборка использует уже обработанные файлы, что существенно ускоряет работу.
При изменении одного файла пересобираются только затронутые модули.
Это особенно важно для крупных приложений.
Трансформация нескольких файлов может выполняться одновременно.
За счет этого значительно сокращается время полной сборки.
Во многих проектах достаточно стандартных возможностей Parcel:
В подобных случаях встроенная интеграция Babel обеспечивает полноценную транспиляцию без создания конфигурационных файлов.
Создание собственной конфигурации Babel оправдано в следующих ситуациях:
Схема обработки JavaScript в Parcel обычно выглядит следующим образом:
Исходный код
│
▼
Анализ целей сборки
│
▼
Babel
│
▼
Трансформированный код
│
▼
Оптимизация Parcel
│
▼
Финальный bundle
Parcel берет на себя определение необходимости трансформации, настройку пайплайна сборки, оптимизацию выходных файлов и интеграцию Babel в общий процесс компиляции, благодаря чему современный JavaScript может использоваться практически без ручной настройки инфраструктуры сборки.