Интеграция со скриптами package.json

Базовая схема подключения сборки через npm-скрипты

В экосистеме Node.js стандартным способом автоматизации задач является использование раздела scripts в package.json. esbuild органично встраивается в этот механизм благодаря своей CLI-утилите, которая позволяет запускать сборку без дополнительного обвязочного кода.

Минимальная конфигурация выглядит следующим образом:

{
  "name": "app",
  "version": "1.0.0",
  "scripts": {
    "build": "esbuild src/index.js --bundle --outfile=dist/bundle.js"
  },
  "devDependencies": {
    "esbuild": "^0.25.0"
  }
}

При вызове:

npm run build

npm автоматически подставляет бинарник esbuild из node_modules/.bin, что исключает необходимость глобальной установки.


Использование npx и локального бинарника

Даже при отсутствии записи в scripts можно запускать esbuild напрямую:

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

Однако такой подход теряет преимущества декларативного управления сборкой. В рамках package.json скрипты становятся единым источником правды для всех команд проекта.


Разделение режимов development и production

Типичная практика — выделение отдельных сценариев сборки под разные среды.

{
  "scripts": {
    "build": "esbuild src/index.js --bundle --outfile=dist/bundle.js --minify",
    "dev": "esbuild src/index.js --bundle --outfile=dist/bundle.js --sourcemap --watch"
  }
}

Ключевые различия:

  • build — оптимизированная сборка с минификацией
  • dev — режим разработки с отслеживанием изменений и sourcemap

Флаг --watch заставляет esbuild отслеживать файловую систему и автоматически пересобирать проект при изменениях.


Композиция скриптов через npm-run-all и цепочки команд

npm позволяет объединять команды через логические операторы:

{
  "scripts": {
    "clean": "rm -rf dist",
    "build": "npm run clean && esbuild src/index.js --bundle --outfile=dist/bundle.js"
  }
}

Здесь сначала выполняется очистка каталога, затем сборка.

В Windows для кроссплатформенности часто используется пакет rimraf:

{
  "scripts": {
    "clean": "rimraf dist"
  }
}

Передача параметров CLI через переменные среды

esbuild поддерживает гибкую конфигурацию через аргументы командной строки, которые можно динамически изменять через npm scripts:

{
  "scripts": {
    "build": "esbuild src/index.js --bundle --outfile=dist/bundle.js --minify=$MINIFY"
  }
}

Запуск:

MINIFY=true npm run build

В Windows требуется использование cross-env:

{
  "scripts": {
    "build": "cross-env MINIFY=true esbuild src/index.js --bundle --outfile=dist/bundle.js --minify"
  }
}

Разделение входных точек и мульти-бандлы

esbuild поддерживает несколько входных файлов, что удобно для многостраничных приложений:

{
  "scripts": {
    "build:main": "esbuild src/main.js --bundle --outfile=dist/main.js",
    "build:admin": "esbuild src/admin.js --bundle --outfile=dist/admin.js"
  }
}

Альтернативно используется единый вызов с несколькими входами:

{
  "scripts": {
    "build": "esbuild src/main.js src/admin.js --bundle --outdir=dist"
  }
}

В этом случае esbuild автоматически создаёт отдельные бандлы для каждого entry point.


Использование –outdir вместо –outfile

При работе с несколькими файлами предпочтительнее использовать --outdir:

{
  "scripts": {
    "build": "esbuild src/*.js --bundle --outdir=dist"
  }
}

Особенности:

  • сохраняется структура входных файлов
  • упрощается масштабирование проекта
  • исключается ручное управление именами выходных файлов

Подключение TypeScript через npm-скрипты

esbuild поддерживает TypeScript без отдельного компилятора:

{
  "scripts": {
    "build": "esbuild src/index.ts --bundle --outfile=dist/bundle.js"
  }
}

Для строгой проверки типов часто комбинируется с tsc:

{
  "scripts": {
    "typecheck": "tsc --noEmit",
    "build": "npm run typecheck && esbuild src/index.ts --bundle --outfile=dist/bundle.js"
  }
}

Интеграция с режимом наблюдения и параллельными процессами

При разработке часто требуется одновременно запускать сервер и сборку. Используется пакет concurrently:

{
  "scripts": {
    "dev": "concurrently \"esbuild src/index.js --bundle --outfile=dist/bundle.js --watch\" \"node server.js\""
  }
}

Такой подход позволяет:

  • изолировать процессы
  • сохранять горячую пересборку
  • не блокировать основной поток Node.js

Использование конфигурационного слоя поверх CLI

Несмотря на ориентацию esbuild на CLI, сложные проекты часто выносят параметры в JavaScript-скрипт:

// build.js
const esbuild = require('esbuild');

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

package.json:

{
  "scripts": {
    "build": "node build.js"
  }
}

Такой подход даёт:

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

Разделение окружений через разные скрипты

Структурирование команд сборки часто оформляется через префиксы:

{
  "scripts": {
    "build:dev": "esbuild src/index.js --bundle --outfile=dist/bundle.js --sourcemap",
    "build:prod": "esbuild src/index.js --bundle --outfile=dist/bundle.js --minify",
    "build:analyze": "esbuild src/index.js --bundle --outfile=dist/bundle.js --metafile=meta.json"
  }
}

Файл metafile.json используется для анализа зависимостей и оптимизации структуры бандла.


Работа с алиасами и упрощением команд

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

{
  "scripts": {
    "esbuild": "esbuild src/index.js --bundle --outfile=dist/bundle.js",
    "build": "npm run esbuild -- --minify"
  }
}

Здесь используется передача аргументов через --, позволяющая расширять базовую команду.


Автоматизация через pre и post скрипты

npm поддерживает автоматические хуки:

{
  "scripts": {
    "prebuild": "rm -rf dist",
    "build": "esbuild src/index.js --bundle --outfile=dist/bundle.js",
    "postbuild": "echo build complete"
  }
}

Порядок выполнения:

  1. prebuild
  2. build
  3. postbuild

Это позволяет строить полноценные пайплайны без внешних инструментов.


Оптимизация больших проектов через разделение сборки

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

{
  "scripts": {
    "build:core": "esbuild src/core/index.js --bundle --outdir=dist/core",
    "build:ui": "esbuild src/ui/index.js --bundle --outdir=dist/ui",
    "build": "npm run build:core && npm run build:ui"
  }
}

Такое разделение:

  • уменьшает время пересборки
  • упрощает отладку
  • позволяет параллелить задачи через внешние инструменты

Интеграция с монорепозиториями

В монорепозиториях esbuild часто вызывается через root package.json:

{
  "scripts": {
    "build": "npm run build --workspace=packages/app"
  }
}

Или через независимые сборки каждого пакета:

{
  "scripts": {
    "build:pkg-a": "npm --prefix packages/pkg-a run build",
    "build:pkg-b": "npm --prefix packages/pkg-b run build"
  }
}

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