Опция bundle включает режим сборки, при котором esbuild
не просто трансформирует отдельный файл, а строит граф зависимостей и
объединяет все импортируемые модули в единый (или несколько) выходных
файлов. Включение этого режима принципиально меняет поведение резолвинга
и обработки импортов.
При значении:
bundle: true
esbuild начинает обход импортов от точки входа и рекурсивно включает зависимости, формируя единый бандл.
При bundle: false (значение по умолчанию) каждый файл
обрабатывается изолированно: import/export остаются в выходном коде
(если формат это поддерживает), а реальное объединение не
происходит.
В режиме bundling esbuild формирует граф модулей, начиная с entry point:
import и requireКлючевой особенностью является агрессивная оптимизация: каждый модуль включается в бандл ровно один раз, даже если он импортируется из разных мест.
Механизм разрешения модулей в esbuild опирается на несколько источников информации:
Простейший случай — относительные импорты:
import utils from "./utils.js";
import helper from "../core/helper.js";
Алгоритм:
.js, .ts, .jsx,
.tsx, .json (в зависимости от контекста)node_modulesИмпорт вида:
import express from "express";
запускает поиск в node_modules:
поиск ближайшего node_modules вверх по дереву
директорий
чтение package.json
определение entry point через поля:
mainmoduleexports (приоритетный современный механизм)exports
и conditional exportsСовременные пакеты часто используют:
{
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
}
}
esbuild учитывает условия экспорта в зависимости от режима сборки:
import — для ESM-сборкиrequire — для CJSbrowser — при target: browsernode,
default)Если поле exports присутствует, оно имеет приоритет над
main.
Разрешение также зависит от типа пакета:
"type": "module" в package.json →
.js трактуется как ESMtype → .js считается
CommonJSЭто влияет на:
requireПри сборке под браузер учитывается:
{
"browser": {
"fs": false,
"./node.js": "./browser.js"
}
}
Это позволяет:
false)bundle в трансформации импортовВ режиме bundling esbuild выполняет преобразование импортов:
import { readFile } from "fs";
external: ["fs"])const lib = require("lib");
переводится в единый модульный формат, совместимый с выбранным output format.
bundle и
externalОпция external напрямую влияет на процесс сборки:
bundle: true,
external: ["react", "react-dom"]
В этом случае:
react и react-dom исключаются из
графаЭто используется для:
esbuild выполняет удаление неиспользуемого кода в процессе построения графа:
Однако есть ограничения:
require() ухудшают анализsideEffects: falseesbuild не интерпретирует paths из
tsconfig.json без плагинов. Для этого используются плагины
резолвинга:
Резолвинг всегда привязан к реальной файловой системе:
При поиске файла порядок может включать:
.tsx.ts.jsx.js.jsonПриоритет зависит от контекста сборки и платформы
(platform: node | browser).
platformОпция platform сильно влияет на resolution:
platform: noderequiremain и exports как в
Nodeplatform: browserbrowser fieldformat на
bundlebundle: true работает совместно с
format:
iife → единый скрипт для браузераesm → единый ESM-бандлcjs → CommonJS сборка для Nodeumd → универсальный форматФормат влияет на:
При наличии циклов:
// a.js
import { b } from "./b.js";
// b.js
import { a } from "./a.js";
esbuild:
При сборке:
При использовании динамического импорта:
import("./module.js");
esbuild:
Опция bundle является обязательной для code
splitting.
Включение bundle приводит к следующим изменениям:
exports в пакетахЕсли модуль не найден:
Типичные причины:
main/exportsnode_modules