esbuild ориентирован на современный JavaScript-ландшафт и работает по принципу транспиляции «из современного в современный», а не «из современного в устаревший ES5». Это ключевое отличие от классических транспайлеров вроде Babel в режиме legacy.
Минимальная целевая планка генерации кода в esbuild — ES2015 (ES6). Поддержка полноценного ES5-вывода отсутствует как архитектурное ограничение.
Это означает:
Основной механизм управления совместимостью — поле
target в конфигурации сборки.
Поддерживаемые значения начинаются с ES2015:
es2015es2016es2017es2018es2019es2020es2021es2022es2023esnextОтсутствие ES5 среди допустимых целей означает принципиальную границу: генерация кода ниже ES2015 не предусмотрена.
Несмотря на отсутствие ES5-таргета, значительная часть современного синтаксиса всё же преобразуется до уровня ES2015.
const add = (a, b) => a + b;
Преобразуется в function expression:
var add = function(a, b) {
return a + b;
};
Это уже ES5-совместимый уровень, так как используется
function и var.
const и let трансформируются в
var:
const x = 1;
let y = 2;
Результат:
var x = 1;
var y = 2;
Однако семантика блочной области видимости частично теряется, что может приводить к отличиям от исходного поведения ES6.
const msg = `Hello ${name}`;
Преобразуются в конкатенацию:
var msg = "Hello " + name;
Классы трансформируются в ES5-подобные функции с прототипами:
class A {
constructor(x) {
this.x = x;
}
getX() {
return this.x;
}
}
Преобразуется в:
function A(x) {
this.x = x;
}
A.prototype.getX = function() {
return this.x;
};
При этом:
extends также преобразуется;super;Поддержка частичная и зависит от контекста.
Пример:
const { a, b } = obj;
Может быть преобразован в доступ к свойствам:
var a = obj.a;
var b = obj.b;
Но сложные паттерны (вложенные структуры, параметры функций) могут преобразовываться не полностью или требовать дополнительной обработки.
const newObj = { ...a, b: 1 };
Может быть преобразован в Object.assign:
var newObj = Object.assign({}, a, { b: 1 });
Это уже ES5-совместимо при наличии Object.assign или его
полифилла.
const arr2 = [...arr1, 2];
Преобразуется в:
var arr2 = arr1.concat([2]);
Ключевое ограничение: невозможно гарантировать генерацию кода, полностью соответствующего ES5-рантайму без дополнительных инструментов.
Причины:
async function load() {
const res = await fetch("/api");
return res.json();
}
Преобразуется в генератороподобную конструкцию или state machine, но:
В ряде случаев результат всё равно ориентирован на ES2015+ окружение.
esbuild не добавляет полифиллы для:
PromiseMap, SetObject.assign (в некоторых конфигурациях требуется
вручную)Array.fromSymbolЭто критическое ограничение для ES5-окружений.
Эти конструкции:
function* gen() {
yield 1;
}
Могут быть трансформированы, но результат не является нативным ES5-кодом и часто требует runtime поддержки генераторов.
@babel/preset-env;При установке:
target: "es2015"
происходит:
Это означает, что итоговый код:
Promise;Map/Set;ES5-ориентированные среды включают:
esbuild не предназначен для прямого обслуживания таких окружений без внешнего слоя полифиллов и дополнительной транспиляции.
Для приближения к ES5 требуется:
esbuild сознательно избегает:
Фокус смещён в сторону:
Типичный подход:
esbuild выполняет:
Babel выполняет:
Такое разделение компенсирует ограничения esbuild.
В некоторых сборках:
или
Несмотря на ограничения, значительная часть синтаксиса упрощается до ES5-эквивалентов:
Эта трансформация даёт «псевдо-ES5 слой», но не полноценную спецификационную совместимость с устаревшими средами выполнения.