Браузерная платформа изначально не содержит значительной части API, которые присутствуют в Node.js. В контексте сборки через esbuild это приводит к важному архитектурному различию: зависимости, рассчитанные на серверную среду, не могут быть использованы в браузере без адаптации.
Ключевые отсутствующие в браузере модули и глобальные объекты:
process (включая process.env)Bufferpath, fs, os,
crypto (Node-реализация)__dirname,
__filename)Esbuild не выполняет автоматическую подмену этих API на полифилы. Это принципиальное решение: сборщик ориентируется на скорость и минимальную трансформацию кода, а не на полноценную эмуляцию среды исполнения.
platform: "browser" и его ограниченияКонфигурация сборки с параметром:
platform: "browser"
влияет только на поведение резолвинга модулей и некоторые встроенные допущения, но не добавляет полифилы.
Основные эффекты:
package.jsonbrowser-версий зависимостей (если они
указаны)Важно: сам по себе этот режим не обеспечивает совместимость Node API с браузером.
browser в package.jsonМногие npm-пакеты предоставляют альтернативную реализацию для браузера:
{
"main": "dist/index.js",
"browser": "dist/browser.js"
}
Esbuild при platform: "browser" автоматически:
browser, если оно присутствуетmodule или main,
если browser отсутствуетТакже поддерживаются маппинги вида:
{
"browser": {
"fs": false,
"path": "./shims/path-browser.js"
}
}
Такой механизм позволяет:
false)Это базовый уровень полифилинга на уровне резолвинга, без вмешательства в код исполнения.
Esbuild сознательно не включает встроенные полифилы. Причины:
В результате любые Node-API в браузере требуют явной стратегии замещения.
defineМеханизм define используется для статической подстановки
значений на этапе сборки.
Пример замены process.env.NODE_ENV:
esbuild.build({
entryPoints: ["src/index.js"],
bundle: true,
platform: "browser",
define: {
"process.env.NODE_ENV": '"production"'
}
});
Характеристики механизма:
processЧасто используется для устранения зависимостей, которые проверяют
окружение через process.env.
processМногие библиотеки ожидают наличие process, особенно
process.env и process.nextTick.
Проблема: в браузере process отсутствует полностью.
Решение через inject:
import process from "process/browser";
esbuild.build({
entryPoints: ["src/app.js"],
bundle: true,
platform: "browser",
inject: ["./shims/process.js"]
});
shims/process.js:
import process from "process/browser";
export { process };
Альтернативный подход — использование готового пакета:
process (npm пакет с browser-реализацией)BufferBuffer активно используется в криптографии, сетевых
библиотеках и кодировках.
Браузерная замена:
import { Buffer } from "buffer";
window.Buffer = Buffer;
Интеграция через esbuild:
inject: ["./shims/buffer.js"]
buffer.js:
import { Buffer } from "buffer";
globalThis.Buffer = Buffer;
Особенности:
processimport path from "path-browserify";
Используется для:
import crypto from "crypto-browserify";
Особенности:
import { Readable } from "stream-browserify";
Применяется в потоковой обработке данных.
import util from "util/";
Частично эмулирует Node API.
inject как механизм глобальных shim-подстановокinject — основной механизм подключения полифилов в
esbuild.
Пример конфигурации:
esbuild.build({
entryPoints: ["src/index.js"],
bundle: true,
platform: "browser",
inject: [
"./shims/process.js",
"./shims/buffer.js"
]
});
Принцип работы:
Ограничения:
requireresolve.alias через плагиныEsbuild не имеет встроенного alias API, но поддерживает плагины.
Пример замены Node модулей:
const polyfillNode = {
name: "polyfill-node",
setup(build) {
build.onResolve({ filter: /^path$/ }, () => ({
path: "path-browserify"
}));
}
};
Использование:
esbuild.build({
entryPoints: ["src/index.js"],
bundle: true,
platform: "browser",
plugins: [polyfillNode]
});
Такой подход позволяет:
На практике используются комплексные наборы:
esbuild-plugin-polyfill-nodenode-stdlib-browseresbuild-plugin-node-globalsОни обычно включают:
processBuffercryptostreamasserturlПри работе с esbuild важно учитывать структуру зависимостей:
Типичная стратегия:
resolve: {
alias: {
fs: false,
net: false,
tls: false
}
}
Исключение модулей:
Многие пакеты используют exports:
{
"exports": {
"browser": "./dist/browser.js",
"node": "./dist/node.js"
}
}
Esbuild учитывает это при platform: "browser", но:
Типовая конфигурация браузерной сборки:
esbuild.build({
entryPoints: ["src/index.js"],
bundle: true,
platform: "browser",
target: "es2018",
define: {
"process.env.NODE_ENV": '"production"'
},
inject: [
"./shims/process.js",
"./shims/buffer.js"
]
});
Дополнительные меры:
fs, net, tlsbrowser поля пакетовПодключение полифилов приводит к ряду последствий:
Некоторые библиотеки используют глубокую зависимость от Node API, что делает их частично несовместимыми даже с полифилами.
Даже при наличии полифилов сохраняются фундаментальные различия:
Эти различия невозможно полностью устранить средствами esbuild или shim-библиотек.