Поддерживаемый синтаксис JavaScript

esbuild использует собственный высокопроизводительный парсер JavaScript/TypeScript, ориентированный на максимально быстрое построение AST без полноценной семантической проверки. Это определяет ключевую особенность поддерживаемого синтаксиса: инструмент стремится корректно разобрать широкий спектр современных конструкций ECMAScript и популярных расширений, но не реализует всю глубину проверки типов или спецификаций TypeScript-компилятора.

Поддержка синтаксиса в esbuild строится вокруг двух принципов:

  • Парсинг современного ECMAScript (ESNext) с акцентом на актуальные версии стандарта.
  • Эвакуация (strip) или трансформация расширений, таких как TypeScript и JSX, без выполнения их полной семантики.

В результате esbuild можно рассматривать как синтаксически «толерантный» инструмент, ориентированный на интерпретацию структуры кода, а не на его статический анализ уровня tsc.


Современный ECMAScript синтаксис

esbuild поддерживает широкий набор конструкций современных версий JavaScript, включая ES2015+ и более новые спецификации, применяемые в текущих движках.

Модули ES (ESM)

Поддерживаются стандартные конструкции модульной системы:

  • import / export
  • именованные и дефолтные экспорты
  • реэкспорт (export * from)
  • динамический импорт

Пример:

import { readFile } from "fs";
export const name = "esbuild";
export default function build() {}

Динамический импорт:

const mod = await import("./module.js");

Особенность esbuild заключается в том, что он не просто парсит эти конструкции, но и активно участвует в бандлинге модулей, сохраняя их семантику или преобразуя в зависимости от режима вывода (ESM/CJS/IIFE).


Современные объявления переменных

Поддерживаются все стандартные формы:

  • let
  • const
  • var

С учётом блочной области видимости:

if (true) {
  let x = 1;
  const y = 2;
}

Стрелочные функции и лексическое this

const fn = (a, b) => a + b;

Поддержка включает:

  • неявный return
  • блочные тела
  • захват лексического this

Классы и расширенный синтаксис ООП

esbuild поддерживает современный class-синтаксис:

  • классы
  • наследование
  • статические методы
  • приватные поля и методы
class A {
  #secret = 1;

  constructor(value) {
    this.value = value;
  }

  getSecret() {
    return this.#secret;
  }

  static create() {
    return new A(10);
  }
}

Private fields и методы

Поддерживаются:

  • #field
  • #method()

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


Optional chaining и nullish coalescing

Одни из ключевых современных операторов:

const value = obj?.nested?.prop;
const result = input ?? "default";

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


Async/await

async function load() {
  const data = await fetch("/api");
  return data.json();
}

Поддерживаются:

  • async функции
  • await в top-level (в ESM-контексте)
  • Promise-based выражения

Top-level await

В модулях ES:

const data = await fetch("/config.json").then(r => r.json());

esbuild корректно обрабатывает такую конструкцию при использовании ESM-вывода.


Синтаксис TypeScript

esbuild поддерживает TypeScript не как систему типизации, а как расширенный синтаксис, который удаляется во время трансформации.

Удаление типов

Все типовые конструкции полностью удаляются:

function add(a: number, b: number): number {
  return a + b;
}

Преобразуется в:

function add(a, b) {
  return a + b;
}

Поддерживаются:

  • аннотации типов
  • интерфейсы
  • type aliases
  • generics (удаляются)
  • enum (компилируются в JS-объекты)
  • type-only imports/exports

Enum

enum Color {
  Red,
  Green,
  Blue
}

Преобразуется в объектную структуру Jav * aScript:

var Color = /* @__PURE__ */ ((Color2) => {
  Color2[Color2["Red"] = 0] = "Red";
  Color2[Color2["Green"] = 1] = "Green";
  Color2[Color2["Blue"] = 2] = "Blue";
  return Color2;
})(Color || {});

Type-only конструкции

Удаляются без влияния на runtime:

type User = {
  name: string;
};

interface Person {
  age: number;
}

TS-расширения выражений

Поддерживаются:

  • non-null assertion !
  • optional parameters
  • parameter properties в классах
class User {
  constructor(public name: string) {}
}

Namespaces

Поддержка ограничена и зависит от режима, но базовая трансформация возможна:

namespace App {
  export const version = "1.0";
}

JSX и TSX синтаксис

esbuild имеет встроенный трансформер JSX, отличающийся высокой скоростью и минимальной конфигурацией.

Базовый JSX

const el = <div>Hello</div>;

Настройки runtime

Поддерживаются два режима:

  • automatic runtime
  • classic runtime

Automatic:

import { jsx } from "react/jsx-runtime";

const el = jsx("div", { children: "Hello" });

Classic:

React.createElement("div", null, "Hello");

JSX expressions

const el = <div>{value}</div>;

Поддерживаются:

  • выражения внутри фигурных скобок
  • условные выражения
  • массивы элементов

TSX

Комбинация JSX + TypeScript:

type Props = {
  title: string;
};

function Comp({ title }: Props) {
  return <h1>{title}</h1>;
}

TypeScript-часть удаляется, JSX трансформируется.


Современные языковые конструкции ECMAScript

Деструктуризация

const { a, b } = obj;
const [x, y] = arr;

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

const { a = 1 } = obj;

Spread и rest

const arr2 = [...arr1, 4];
const { a, ...rest } = obj;

Template literals

const msg = `Hello ${name}`;

Поддерживаются многострочные строки и интерполяция.


Усовершенствованные параметры функций

function fn(a = 1, ...rest) {}

Особенности обработки модулей и синтаксических границ

esbuild строго различает:

  • модульный код (ESM)
  • CommonJS
  • IIFE

При этом синтаксис парсится единообразно, но поведение вывода зависит от target и format.

CommonJS конструкции

const fs = require("fs");
module.exports = {};

esbuild поддерживает их при соответствующем режиме сборки.


Динамические require

const mod = require(path);

Поддерживается как часть CommonJS-семантики.


Ограничения синтаксического анализа

Несмотря на широкую поддержку современного JS, esbuild не является полноценным компилятором языка с глубокой семантической моделью.

Отсутствие type-checking

TypeScript типы:

  • не проверяются
  • не анализируются на корректность
  • просто удаляются

Ограничения некоторых экспериментальных фич

Часть stage-3/experimental фич может:

  • поддерживаться частично
  • требовать включения определённых настроек target
  • зависеть от версии esbuild

Decorators

Поддержка декораторов существует, но их поведение зависит от режима (legacy vs TC39 proposal). В современных конфигурациях используется приближённая к стандарту трансформация.

function deco(target: any) {}

@deco
class A {}

Отсутствие поддержки некоторых синтаксических экзотик

Могут не поддерживаться или ограниченно поддерживаться:

  • устаревшие нестандартные TypeScript-расширения
  • специфические Babel-плагины синтаксиса
  • кастомные макро-синтаксисы

Влияние синтаксиса на процесс бандлинга

Поддерживаемый синтаксис напрямую связан с тем, как esbuild выполняет трансформацию:

  • AST строится максимально быстро
  • синтаксис нормализуется под target environment
  • TypeScript и JSX удаляются/преобразуются до JS
  • ESM/CJS граф модулей строится на основе import/export

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