Загрузка модулей в esbuild основана на жёстко детерминированной системе загрузчиков (loaders), где ключевую роль играет расширение файла и явная конфигурация сборщика. Поведение по умолчанию построено вокруг принципа минимального анализа содержимого и максимальной скорости: файл почти всегда обрабатывается не по содержимому, а по имени и расширению.
Каждый импортируемый файл в esbuild проходит через слой определения loader-а. Loader определяет, как именно интерпретировать содержимое модуля:
Ключевой принцип: loader всегда выбирается до анализа содержимого файла.
Если loader явно не указан, esbuild применяет встроенное правило сопоставления расширений.
| Расширение | Loader |
|---|---|
.js, .cjs, .mjs |
js |
.ts |
ts |
.tsx |
tsx |
.jsx |
jsx |
.json |
json |
.css |
css |
.txt (и похожие текстовые) |
text (в зависимости от контекста) |
| неизвестные расширения | file |
Это сопоставление является первой и основной стадией автоопределения.
esbuild не анализирует содержимое файла для выбора loader-а. Нет проверки вроде “похоже ли это на JSON” или “содержит ли JSX”.
Выбор происходит исключительно по расширению.
Автоопределение loader-а в esbuild — это не «интеллектуальный анализ», а строгая таблица соответствий.
Порядок действий следующий:
file)import data from "./config.json";
import Component from "./App.jsx";
import utils from "./utils.ts";
import image from "./logo.png";
Результат обработки:
config.json → jsonApp.jsx → jsxutils.ts → tslogo.png → filefile как
fallbackОсобую роль играет loader file. Он применяется ко всему,
что не попало под известные расширения.
fileПример:
import logo from "./assets/logo.svg";
При отсутствии явного loader-а:
logo.svg → fileНа выходе:
export default "/assets/logo.hash.svg";
(реальный результат зависит от настройки outdir и
publicPath)
Несмотря на автоопределение, конфигурация loader
позволяет переопределить поведение.
import { build } from "esbuild";
build({
entryPoints: ["src/index.js"],
bundle: true,
outfile: "dist/bundle.js",
loader: {
".js": "jsx",
".png": "dataurl",
".svg": "text"
}
});
jsИспользуется для:
.js.mjs.cjsПоведение:
jsxИспользуется для файлов с JSX-синтаксисом.
loader: {
".js": "jsx"
}
Это важно, так как по умолчанию .js не содержит
JSX-трансформации.
ts и tsxts — TypeScript без JSXtsx — TypeScript с JSXesbuild не проверяет содержимое файла: наличие типов или JSX не определяется автоматически.
jsonJSON-файлы превращаются в ES Module:
{
"name": "app",
"version": "1.0.0"
}
После импорта:
import pkg from "./package.json";
console.log(pkg.version);
Результат — объект JavaScript.
cssCSS обрабатывается как модуль:
Автоопределение строго по .css.
textСодержимое читается как строка.
Полезно для:
binary и base64Используются для бинарных данных:
binary — ArrayBufferbase64 — строка base64dataurlПреобразует файл в Data URL:
data:image/png;base64,...
Часто используется для изображений небольшого размера.
Файл с расширением .js всегда считается JavaScript, даже
если внутри JSON:
// config.js (на самом деле JSON по содержимому)
{
"mode": "test"
}
esbuild обработает это как JS и выдаст ошибку.
Это делает систему:
JSX не распознаётся внутри .js автоматически.
// даже если здесь JSX
const el = <div />;
Без loader jsx будет синтаксическая ошибка.
fileimport config from "./config.toml";
Если loader не задан:
.toml → fileИ файл не парсится как структура данных.
Иерархия выбора:
fileВажно: конфигурация всегда имеет приоритет над автоопределением.
loader: {
".md": "text",
".svg": "text",
".graphql": "text"
}
Здесь автоопределение полностью расширяется вручную.
loader: {
".js": "jsx"
}
Позволяет использовать JSX без переименования файлов.
loader: {
".png": "dataurl",
".jpg": "dataurl"
}
Удобно для небольших изображений и UI-иконок.
Отказ от анализа содержимого — ключевая оптимизация esbuild:
Это одна из причин высокой скорости сборки по сравнению с инструментами, где используется более сложная логика определения типа модуля.
import App from "./App.js";
Если файл содержит JSX, но имеет .js, без
переопределения:
import data from "./config.txt";
Даже если внутри JSON — результат будет строка.
SVG, TOML, YAML не поддерживаются без явного указания.
Автоопределение loader-а в esbuild можно свести к простой модели:
loader(file) =
if (loader_override exists) → override
else if (extension in table) → mapped loader
else → file
Эта модель подчёркивает фундаментальный принцип esbuild: простота правил вместо анализа содержимого, что обеспечивает предсказуемость и высокую скорость обработки модулей.