В системах сборки JavaScript разрешение входных точек модулей часто
зависит от структуры package.json. Пакет может содержать
несколько альтернативных полей, указывающих на разные сборочные
артефакты: для браузера, для ESM, для CommonJS или для специфичных
окружений. Esbuild предоставляет механизм управления приоритетом этих
полей через опцию mainFields, определяющую порядок, в
котором анализируются ключи внутри package.json.
mainFields в разрешении модулейПри импорте модуля из npm-пакета сборщик сталкивается с задачей выбора конкретного файла, указанного в метаданных пакета. Один и тот же пакет может содержать несколько входных точек:
{
"main": "dist/index.cjs",
"module": "dist/index.mjs",
"browser": "dist/index.browser.js"
}
Каждое поле предназначено для разных сценариев:
main — классический CommonJS-экспортmodule — ES Module версияbrowser — версия, оптимизированная под браузерОпция mainFields определяет, какое из этих полей будет
выбрано первым.
Esbuild использует разумные дефолты, ориентированные на современную экосистему:
для platform: "browser":
mainFields: ["browser", "module", "main"]для platform: "node":
mainFields: ["main", "module"]Этот порядок отражает приоритетность:
browser или
main)module)main)При импорте пакета Esbuild выполняет следующие шаги:
package.json целевого пакетаmainFieldsПример:
{
"browser": "dist/browser.js",
"module": "dist/module.js",
"main": "dist/index.js"
}
При конфигурации:
{
platform: "browser",
mainFields: ["module", "main"]
}
будет выбран dist/module.js, потому что
module стоит выше main.
Порядок в mainFields напрямую влияет на итоговый бандл.
Небольшое изменение приоритета может привести к:
Особенно критично это для библиотек, которые предоставляют разные сборки под разные среды.
browser, module, mainbrowserИспользуется для клиентских сборок. Часто содержит:
Пример:
"browser": {
"fs": false,
"./server.js": "./browser.js"
}
moduleESM-версия пакета. Используется для:
mainУниверсальный CommonJS entry point. Используется как fallback для сред без ESM-оптимизаций или когда другие поля отсутствуют.
mainFields в EsbuildОпция передаётся в конфигурации сборки:
import esbuild from "esbuild";
esbuild.build({
entryPoints: ["src/index.js"],
bundle: true,
platform: "browser",
mainFields: ["browser", "module", "main"],
outfile: "dist/bundle.js"
});
Изменение порядка:
mainFields: ["module", "main", "browser"]
может привести к тому, что даже в браузерной сборке будет использована ESM-версия без browser-specific замен.
platform на
mainFieldsПараметр platform тесно связан с
mainFields.
platform: "browser"browser → module → mainplatform: "node"main → moduleplatform: "neutral"В нейтральном режиме Esbuild не навязывает жёсткой логики, и
поведение зависит от явно указанных mainFields.
exportsСовременные пакеты часто используют поле exports,
которое частично перекрывает mainFields.
Пример:
{
"exports": {
".": {
"browser": "./dist/browser.js",
"import": "./dist/module.js",
"require": "./dist/index.cjs"
}
}
}
В этом случае:
exports имеет приоритет над
mainFieldsmainFields используется только если
exports не определяет путьТаким образом, mainFields становится fallback-механизмом
для старых или упрощённых пакетов.
Если ни одно поле из mainFields не найдено:
index.js в корне пакетаpackage.json-дефолты Node-стиляВыбор поля напрямую влияет на возможность удаления неиспользуемого кода:
module) позволяет статически анализировать
зависимостиmain) ограничивает оптимизациюТаким образом, неправильный порядок mainFields может
привести к:
Рассмотрим три варианта конфигурации:
mainFields: ["browser", "module", "main"]
Поведение:
mainFields: ["module", "main"]
Поведение:
mainFields: ["main"]
Поведение:
При использовании alias и кастомного
resolve порядок mainFields всё ещё применяется
после сопоставления алиасов:
aliaspackage.jsonmainFieldsВ монорепозиториях часто встречаются пакеты с разной структурой сборок. В таких условиях:
mainFields становится способом унифицировать
поведениеСлишком высокий приоритет main
Игнорирование browser
Несогласованность между пакетами
Хотя mainFields не влияет напрямую на минификацию, он
определяет:
В production-сценариях выбор module чаще всего даёт
наиболее эффективный результат.
Современные пакеты стремятся поддерживать одновременно:
main)module)browser)exportsmainFields в Esbuild служит механизмом интерпретации
этих слоёв, когда exports отсутствует или не полностью
определён.
Логика выбора входного файла можно представить как последовательность приоритетов:
exports (если существует)mainFields (если exports не
определён)index.js fallbackИменно второй уровень определяет поведение mainFields,
делая его критическим параметром для контроля сборки зависимостей.