npm:esbuild и deno.land/x

esbuild представляет собой высокопроизводительный бандлер и минификатор JavaScript/TypeScript, ориентированный на скорость сборки и минимальные накладные расходы. В экосистеме Node.js он распространяется через npm как esbuild, а в Deno может использоваться через npm-совместимый слой или через сторонние обёртки в репозитории Deno, включая зависимости из deno.land/x.


npm:esbuild — установка и базовая интеграция

В Node.js среде esbuild устанавливается стандартным способом:

npm install esbuild

После установки доступно два основных способа использования:

  1. CLI-интерфейс
  2. JavaScript API

CLI-использование

CLI esbuild позволяет быстро выполнять сборку без написания кода:

npx esbuild src/index.js --bundle --outfile=dist/bundle.js

Ключевые параметры:

  • --bundle — включает сборку модулей в единый файл
  • --outfile — путь выходного файла
  • --minify — минификация кода
  • --platform=node|browser — целевая среда выполнения
  • --target=es2020 — уровень поддержки ECMAScript

Минимизация и сборка TypeScript без конфигурации:

npx esbuild src/app.ts --bundle --minify --outfile=dist/app.js

JavaScript API esbuild

API esbuild ориентирован на сценарии интеграции в сборочные системы и dev-серверы.

Базовая сборка

import * as esbuild from 'esbuild';

await esbuild.build({
  entryPoints: ['src/index.ts'],
  bundle: true,
  outfile: 'dist/bundle.js',
  minify: true,
  target: ['es2020']
});

Режим watch

await esbuild.context({
  entryPoints: ['src/index.ts'],
  bundle: true,
  outfile: 'dist/bundle.js'
}).then(ctx => {
  return ctx.watch();
});

Watch-режим работает через инкрементальную пересборку, используя внутренний кэш графа зависимостей.


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

esbuild написан на Go, что принципиально отличает его от большинства JS-бандлеров. Это даёт:

  • параллельный разбор файлов
  • минимальные задержки при старте
  • отсутствие тяжёлых JS-абстракций в ядре
  • эффективное использование памяти

Ключевая особенность — отказ от сложных плагинных цепочек в пользу упрощённого API трансформаций.


Трансформация модулей

esbuild поддерживает:

  • ES Modules (import/export)
  • CommonJS (require/module.exports)
  • TypeScript без предварительной компиляции
  • JSX (React и совместимые рантаймы)

Пример JSX:

await esbuild.build({
  entryPoints: ['src/app.jsx'],
  bundle: true,
  jsxFactory: 'h',
  jsxFragment: 'Fragment',
  outfile: 'dist/app.js'
});

Плагины esbuild

Плагинная система esbuild минималистична и основана на хуках onResolve и onLoad.

import * as esbuild from 'esbuild';

const examplePlugin = {
  name: 'example',
  setup(build) {
    build.onResolve({ filter: /.txt$/ }, args => {
      return { path: args.path, namespace: 'txt' };
    });

    build.onLoad({ filter: /.txt$/, namespace: 'txt' }, args => {
      return {
        contents: 'export default "text content"',
        loader: 'js'
      };
    });
  }
};

await esbuild.build({
  entryPoints: ['src/index.js'],
  bundle: true,
  outfile: 'dist/out.js',
  plugins: [examplePlugin]
});

esbuild и Deno: модель интеграции

В Deno отсутствует классическая node_modules-модель, но существует несколько способов использования esbuild.

Использование npm-совместимости Deno

Современные версии Deno поддерживают импорт npm-пакетов напрямую:

import * as esbuild from "npm:esbuild";

await esbuild.build({
  entryPoints: ["./main.ts"],
  bundle: true,
  outfile: "./dist/bundle.js"
});

Этот механизм транслирует npm-зависимости в Deno runtime без необходимости установки через npm CLI.


Deno.land/x и сторонние обёртки

deno.land/x представляет собой реестр сторонних модулей для Deno, где публикуются обёртки и адаптации библиотек.

В контексте esbuild чаще встречаются следующие подходы:

1. Обёртки над esbuild

Некоторые модули на deno.land/x предоставляют API для запуска esbuild как процесса или WASM-версии:

import { build } from "https://deno.land/x/esbuild/mod.ts";

await build({
  entryPoints: ["./src/main.ts"],
  bundle: true,
  outfile: "./dist/app.js"
});

2. Использование esbuild-wasm

Альтернативная стратегия — WebAssembly-версия:

import * as esbuild from "https://deno.land/x/esbuild_wasm/mod.js";

await esbuild.initialize({
  wasmURL: "https://unpkg.com/esbuild-wasm/esbuild.wasm"
});

const result = await esbuild.transform("const x: number = 1", {
  loader: "ts"
});

WASM-версия снижает производительность относительно Go-бинарника, но обеспечивает кросс-платформенность.


Различия подходов Node.js и Deno

Node.js (npm:esbuild)

  • нативный бинарник Go
  • высокая производительность
  • прямой доступ к файловой системе через Node API
  • зрелая интеграция с bundler-экосистемой

Deno (deno.land/x и npm:)

  • sandbox-модель с разрешениями
  • возможность импортировать npm напрямую
  • альтернативные WASM-сборки
  • более строгая безопасность исполнения

Инкрементальная сборка и контекст выполнения

esbuild поддерживает context API, который особенно полезен в долгоживущих процессах:

import * as esbuild from 'esbuild';

const ctx = await esbuild.context({
  entryPoints: ['src/index.ts'],
  bundle: true,
  outfile: 'dist/app.js'
});

await ctx.watch();

Инкрементальная модель снижает стоимость повторной сборки за счёт переиспользования AST и графа зависимостей.


Управление зависимостями и резолвинг

esbuild использует собственный алгоритм разрешения модулей:

  • относительные пути (./, ../)
  • bare imports (через node_modules)
  • aliasing через плагины
  • поддержка условных полей package.json (module, main, browser)

В Deno резолвинг отличается:

  • URL-импорты
  • кеширование модулей в глобальном кеше
  • возможность использования import maps

Производственные сценарии использования

Сборка фронтенда

  • React/Vue/Svelte приложения
  • минификация JS/CSS
  • разделение чанков (ограниченно через плагины)

Backend сборка

  • упаковка Node.js сервисов
  • транспиляция TypeScript в JS
  • подготовка serverless функций

Deno-среда

  • сборка TypeScript без tsc
  • генерация бандлов для edge runtime
  • использование WASM-версий в изолированных средах

Ограничения модели esbuild

Несмотря на высокую скорость, архитектура накладывает ограничения:

  • ограниченная система плагинов
  • отсутствие сложного code-splitting сценарного уровня (по сравнению с Webpack)
  • минимальная runtime-логика
  • ограниченные возможности HMR без внешних инструментов

Взаимодействие npm и deno.land/x в одном проекте

В смешанных проектах возможна комбинация:

  • Deno как runtime
  • esbuild через npm-импорт
  • вспомогательные утилиты из deno.land/x

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

import * as esbuild from "npm:esbuild";
import { copy } from "https://deno.land/x/copy/mod.ts";

await esbuild.build({
  entryPoints: ["./src/main.ts"],
  bundle: true,
  outfile: "./dist/app.js"
});

await copy("./static", "./dist/static");

Такая модель объединяет производительность esbuild и модульную экосистему Deno.