Опция platform: browser, node, neutral

Опция platform определяет, под какую среду выполнения выполняется сборка: браузер, Node.js или универсальная среда. Она влияет не только на поведение резолвинга модулей, но и на набор встроенных полифиллов, обработку стандартной библиотеки, а также на то, какие экспорты и условные поля пакетов будут считаться при бандлинге.

Ключевое влияние platform проявляется в трёх аспектах:

  • выбор встроенных модулей и их замена;
  • логика резолвинга зависимостей из node_modules;
  • поведение совместимости с API окружения (DOM или Node.js runtime).

browser

Значение platform: "browser" задаёт режим сборки для клиентской среды выполнения в браузере.

Особенности поведения

При этом режиме:

  • встроенные Node.js модули считаются недоступными (fs, path, crypto и др.);
  • многие Node-специфичные зависимости либо исключаются, либо требуют внешних полифиллов;
  • при резолвинге приоритет отдаётся полям browser в package.json;
  • минимизируется использование Node-ориентированных API.

Резолвинг зависимостей

В браузерном режиме esbuild учитывает:

  • "browser" field в package.json как основной источник замены модулей;
  • fallback-логику для ESM/CJS в сторону браузерных версий пакетов;
  • игнорирование node-специфичных экспортах, если есть браузерная альтернатива.

Пример поведения package.json:

{
  "main": "index.node.js",
  "browser": "index.browser.js"
}

В режиме browser будет выбран index.browser.js.

Встроенные модули

Любая попытка импортировать Node.js core API:

import fs from "fs";

в браузерной сборке приведёт к ошибке или пустому shim-результату в зависимости от конфигурации (inject, define, внешние пакеты).

Типичные сценарии использования

  • SPA-приложения;
  • библиотеки для фронтенда;
  • React/Vue/Svelte приложения;
  • Web Workers (частично, с ограничениями).

node

Значение platform: "node" предназначено для сборки под Node.js runtime.

Ключевые особенности

  • все встроенные модули Node.js доступны без полифиллов;
  • приоритет резолвинга отдаётся полю main, module, exports, но с учётом Node-условий;
  • поддерживаются условные экспорты require, import, node, default;
  • отсутствует попытка эмулировать браузерные API.

Поведение exports и conditional exports

Node-платформа активирует строгую модель package.json exports:

{
  "exports": {
    ".": {
      "node": "./dist/node.js",
      "import": "./dist/esm.js",
      "require": "./dist/cjs.js"
    }
  }
}

В режиме node приоритет будет:

  1. node
  2. import или require в зависимости от формата сборки
  3. default

Работа с core-модулями

Node platform:

import path from "path";
import fs from "fs/promises";

оставляет импорты без изменений, без полифиллов и транспиляции.

Использование

  • серверные приложения (API, SSR);
  • CLI-инструменты;
  • backend-сервисы;
  • тестовые среды Node.js.

neutral

Значение platform: "neutral" задаёт абстрактную платформу без привязки к Node.js или браузеру.

Основная концепция

Neutral-режим используется, когда:

  • библиотека должна работать в любой среде;
  • нет предположений о наличии DOM или Node API;
  • требуется минимальная трансформация зависимостей.

Поведение резолвинга

  • не применяется логика browser field;
  • не применяется Node-specific resolution;
  • используется базовая стратегия ESM/CJS без платформенных предпочтений;
  • conditional exports обрабатываются нейтрально.

Встроенные модули

В отличие от node, встроенные модули:

  • не подставляются автоматически;
  • считаются внешними, если не настроено иное;
  • требуют явной обработки через external или inject.

Практическое значение

Neutral часто используется для:

  • библиотек общего назначения;
  • универсальных SDK;
  • кода, который будет обёрнут другим бандлером;
  • инструментов, работающих и в браузере, и в Node при разных сборках.

Сравнение поведения платформ

Резолвинг пакетов

  • browser → приоритет browser field
  • node → приоритет Node conditional exports
  • neutral → минимальный набор правил без платформенных предпочтений

Core modules

  • browser → запрещены или заменяются
  • node → доступны напрямую
  • neutral → считаются внешними по умолчанию

Conditional exports

  • browser → игнорирует node-условия
  • node → учитывает node/import/require
  • neutral → обрабатывает без приоритета платформы

Влияние на output и формат сборки

platform не изменяет напрямую формат вывода (iife, cjs, esm), но влияет на содержимое результата:

  • наличие или отсутствие shim-кода;
  • включение полифиллов;
  • резолвинг зависимостей в итоговый bundle;
  • поведение tree-shaking для platform-specific branches.

Взаимодействие с внешними зависимостями

external + platform

Комбинация external и platform даёт контроль над границами среды:

  • в browser часто помечают Node core как external;
  • в node редко требуется external для core-модулей;
  • в neutral external используется для явного указания среды.

Практические конфигурации

Браузерная сборка

esbuild.build({
  entryPoints: ["src/index.js"],
  bundle: true,
  platform: "browser",
  target: "es2018"
});

Node.js сборка

esbuild.build({
  entryPoints: ["src/server.js"],
  bundle: true,
  platform: "node",
  target: "node18"
});

Универсальная библиотека

esbuild.build({
  entryPoints: ["src/lib.js"],
  bundle: true,
  platform: "neutral",
  format: "esm"
});

Особенности взаимодействия с target

platform и target работают совместно, но отвечают за разные уровни:

  • platform → окружение (API, резолвинг, core modules)
  • target → уровень JavaScript синтаксиса и трансформаций

Пример:

  • platform: "browser", target: "es2015" → удаление Node API + транспиляция под старые браузеры
  • platform: "node", target: "node20" → сохранение Node API + минимальные трансформации
  • platform: "neutral" → только синтаксис, без предположений о runtime

Edge cases резолвинга

Пакеты без browser field

В browser режиме без browser поля:

  • используется main или module;
  • возможны несовместимости при Node-зависимых пакетах.

Dual packages (CJS + ESM)

При разных platform:

  • node корректно выбирает exports conditionals;
  • browser может обходить CJS ветки;
  • neutral не гарантирует корректный выбор.

Вложенные зависимости с platform-specific логикой

Некоторые библиотеки содержат:

{
  "browser": {
    "fs": false
  }
}

Это приводит к замене импортов на пустые модули в browser режиме.


Роль в архитектуре сборки

platform формирует базовую модель окружения, вокруг которой строится:

  • стратегия tree-shaking;
  • обработка polyfill/inject;
  • резолвинг пакетов;
  • финальная структура бандла.

В сложных проектах (монорепозитории, универсальные SDK, SSR-приложения) различие между browser, node и neutral становится определяющим фактором корректности результата сборки.