Назначение loader в esbuild заключается в том, чтобы определить, как именно инструмент должен обрабатывать файлы с конкретными расширениями в процессе сборки. В отличие от классических бандлеров, где загрузчики часто представляют собой цепочку трансформаций, в esbuild loader — это строгое сопоставление расширения файла и способа его интерпретации внутри графа зависимостей.
Каждый модуль, который попадает в процесс сборки, идентифицируется по расширению файла. На основании этого расширения esbuild выбирает соответствующий loader и решает, что делать с содержимым:
Ключевая идея заключается в том, что loader не анализирует содержимое файла глубоко — он работает на уровне типа ресурса.
В конфигурации esbuild доступен набор встроенных загрузчиков, каждый из которых выполняет строго определённую роль:
Каждый loader отвечает за то, как импорт будет представлен в итоговом бандле.
В JavaScript API esbuild загрузчики задаются через объект
loader, где ключом выступает расширение файла:
import * as esbuild from 'esbuild';
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outdir: 'dist',
loader: {
'.js': 'js',
'.png': 'file',
'.svg': 'text',
'.json': 'json'
}
});
В этом примере разные типы файлов обрабатываются по-разному:
Связка расширения и loader является ключевым механизмом управления ресурсами. Например:
loader: {
'.png': 'file',
'.jpg': 'file',
'.css': 'text',
'.wasm': 'binary'
}
Здесь видно, что:
Loader file изменяет модель импорта. Вместо содержимого
файла возвращается строка-URL, указывающая на итоговый файл в
сборке:
import logoUrl from './logo.png';
console.log(logoUrl);
После сборки logoUrl будет содержать путь вроде:
assets/logo-8f3a2c.png
Это позволяет работать с ассетами как с обычными модулями, не перегружая JavaScript-код бинарными данными.
Loader text преобразует содержимое файла в строку:
import template from './template.html';
console.log(template);
В результате переменная template содержит весь HTML как
текстовую строку. Это полезно для:
JSON-файлы обрабатываются как JavaScript-объекты:
import data from './config.json';
console.log(data.apiUrl);
При этом esbuild выполняет статическую инлайнизацию JSON, что
исключает необходимость runtime-парсинга через
JSON.parse.
Loader base64 преобразует файл в строку base64:
loader: {
'.png': 'base64'
}
Использование:
import icon from './icon.png';
const img = new Image();
img.src = `data:image/png;base64,${icon}`;
Такой подход полезен для маленьких ресурсов, где важно уменьшить количество HTTP-запросов.
Loader binary возвращает содержимое файла в виде
Uint8Array:
import wasmBytes from './module.wasm';
Дальше эти данные можно использовать, например, для инициализации WebAssembly:
WebAssembly.instantiate(wasmBytes);
Для языков с расширенным синтаксисом используются специализированные загрузчики:
loader: {
'.tsx': 'tsx',
'.ts': 'ts',
'.jsx': 'jsx'
}
Их задача — преобразовать исходный код в чистый JavaScript до этапа связывания модулей.
JSX преобразуется в вызовы React.createElement или
аналогичные структуры, а TypeScript — в JavaScript с удалением
типов.
esbuild использует точное сопоставление расширений. Это означает:
.js и .mjs считаются разными ключами;.ts и .tsx требуют отдельного
указания;Пример:
loader: {
'.ts': 'ts'
}
Файлы .tsx в этом случае не будут обрабатываться
корректно без дополнительной настройки.
Если loader не указан явно, esbuild применяет стандартные правила:
js;json;file в зависимости от контекста;Это делает конфигурацию предсказуемой: поведение всегда определяется либо стандартом, либо явной настройкой.
В CLI esbuild загрузчики задаются через флаг
--loader:
esbuild src/index.js \
--bundle \
--outdir=dist \
--loader:.png=file \
--loader:.svg=text
Каждое расширение указывается отдельно, что делает конфигурацию явной и читаемой.
Loader тесно взаимодействует с другими механизмами сборки:
bundle — влияет на то, как модули объединяются;splitting — влияет на разделение кода;assetNames — управляет именованием файлов при loader
file;publicPath — влияет на формирование URL.Пример:
esbuild.build({
entryPoints: ['src/app.ts'],
bundle: true,
outdir: 'dist',
publicPath: '/static',
assetNames: 'assets/[name]-[hash]',
loader: {
'.png': 'file'
}
});
В этом случае loader определяет тип обработки ресурса, а остальные параметры формируют итоговую структуру вывода.
Модель loader в esbuild намеренно упрощена:
Эта ограниченность компенсируется высокой скоростью и предсказуемостью поведения.
При проектировании сборки обычно применяется следующая логика:
filebase64textjsonbinaryТакое разделение позволяет контролировать баланс между скоростью загрузки и размером бандла.
Если в конфигурации указано несколько правил для одного и того же расширения, последнее определение перекрывает предыдущие:
loader: {
'.png': 'file',
'.png': 'base64'
}
Фактически будет применён base64. Это важно учитывать
при генерации конфигураций программно.
Внутри esbuild весь процесс можно свести к следующей логике:
Эта модель делает систему предельно детерминированной и легко прогнозируемой при масштабировании проектов.