Loader binary

Назначение бинарного лоадера

В esbuild поддержка бинарных файлов реализуется через механизм loader’ов, которые определяют, как именно обрабатывать импортируемые ресурсы. Лоадер binary предназначен для загрузки файлов как сырых бинарных данных, без преобразования в текст, JSON или JavaScript-код.

Основная идея заключается в том, что файл рассматривается как последовательность байтов, которые можно передать дальше по цепочке сборки или использовать в runtime через Uint8Array.

Поведение loader:binary

При использовании loader: 'binary' esbuild:

  • читает файл как поток байтов
  • не выполняет декодирование в строку
  • не интерпретирует содержимое
  • экспортирует данные в виде Uint8Array

Фактически модуль превращается в структуру, пригодную для работы с низкоуровневыми данными.

Пример:

import imageData from './image.png';

console.log(imageData);

После сборки imageData будет представлять собой Uint8Array, содержащий содержимое PNG-файла.


Механизм работы внутри esbuild

Этап загрузки

Когда esbuild встречает импорт файла с бинарным лоадером, происходит следующий процесс:

  1. Файл читается с диска как Buffer
  2. Данные конвертируются в массив байтов
  3. Формируется модульный экспорт
  4. Результат встраивается в бандл или остаётся внешним (в зависимости от настроек)

Представление данных

Внутренне бинарный файл преобразуется примерно в такую структуру:

export default new Uint8Array([137, 80, 78, 71, ...]);

Это делает возможным:

  • использование в Web APIs (Blob, FileReader)
  • передачу в WebAssembly
  • работу с криптографическими или мультимедийными данными
  • обработку файлов без промежуточного текстового слоя

Области применения loader:binary

Работа с изображениями

Бинарный лоадер часто применяется для загрузки изображений на уровне байтов, когда требуется:

  • кастомная обработка форматов
  • декодирование вручную
  • передача в canvas через createImageBitmap

Пример:

import png from './icon.png';

createImageBitmap(new Blob([png]));

WebAssembly

Один из ключевых сценариев использования — загрузка .wasm модулей:

import wasmBinary from './module.wasm';

WebAssembly.instantiate(wasmBinary);

Хотя в реальных проектах часто применяется loader: 'file' или специализированная обработка, бинарный лоадер позволяет полностью контролировать процесс инициализации.


Криптография и бинарные протоколы

В низкоуровневых задачах бинарный лоадер используется для:

  • чтения ключей
  • загрузки сертификатов
  • работы с бинарными протоколами (protobuf, msgpack)
  • обработки зашифрованных пакетов
import keyData from './key.bin';

crypto.subtle.importKey(
  'raw',
  keyData,
  'AES-GCM',
  true,
  ['encrypt', 'decrypt']
);

Отличие от других лоадеров

loader:base64

  • преобразует файл в строку Base64
  • увеличивает размер данных
  • удобен для вставки в текстовые форматы

loader:text

  • интерпретирует файл как UTF-8 строку
  • подходит только для текстовых данных

loader:json

  • парсит содержимое как JSON
  • применим только к структурированным данным

loader:binary

  • сохраняет исходные байты без изменений
  • минимальный уровень абстракции
  • максимальная универсальность для бинарных данных

Особенности поведения в сборке

Инлайнинг

При включённой опции инлайнинга esbuild может:

  • встраивать бинарные данные прямо в JS-бандл
  • увеличивать размер итогового файла
  • устранять необходимость HTTP-запросов

Внешние файлы

При настройках вроде external или assetNames:

  • бинарные данные могут быть вынесены в отдельный файл
  • импорт превращается в ссылку на ресурс

Ограничения

Несмотря на универсальность, loader binary имеет ряд ограничений:

  • увеличивает размер JS при инлайне
  • не подходит для больших файлов без внешнего хранения
  • требует дополнительной обработки в runtime для сложных форматов
  • не предоставляет метаданных о структуре файла

Взаимодействие с TypeScript

При использовании TypeScript необходимо явно описывать тип результата:

declare module '*.bin' {
  const value: Uint8Array;
  export default value;
}

Без этого компилятор будет трактовать импорт как any.


Использование в плагинах esbuild

В плагинах можно вручную эмулировать поведение binary loader:

onLoad({ filter: /\.bin$/ }, async (args) => {
  const fs = await import('fs/promises');
  const data = await fs.readFile(args.path);
  
  return {
    contents: data,
    loader: 'binary'
  };
});

Это позволяет:

  • переопределять стандартную обработку
  • добавлять кэширование
  • модифицировать байты перед экспортом

Производительность

Бинарный лоадер оптимизирован для:

  • минимального количества преобразований
  • прямой передачи данных в память
  • отсутствия парсинга

Однако важно учитывать:

  • большие файлы увеличивают нагрузку на сборку
  • инлайнинг может замедлять загрузку бандла
  • предпочтительно использовать code splitting или external assets для крупных ресурсов

Внутренние сценарии оптимизации

esbuild может применять:

  • shared buffers для одинаковых ресурсов
  • дедупликацию бинарных данных
  • ленивую загрузку при динамических импортах

Пример динамического импорта:

const data = await import('./large.bin');

В этом случае загрузка может быть отложена до момента вызова.


Практические паттерны использования

Хранение встроенных ресурсов

import font from './font.bin';

document.fonts.add(new FontFace('Custom', font));

Передача в Web Workers

import payload from './payload.bin';

worker.postMessage(payload);

Обработка собственных форматов

import packet from './packet.bin';

function parsePacket(data) {
  const view = new DataView(data.buffer);
  return view.getUint32(0);
}

Роль в архитектуре сборки

Loader binary занимает промежуточное положение между:

  • asset pipeline (файловые ресурсы)
  • runtime data handling (данные приложения)

Он позволяет esbuild работать не только как JS-бандлер, но и как инструмент для транспортировки произвольных данных через систему модулей ECMAScript.