Импорт WebAssembly

Parcel рассматривает WebAssembly как полноценный тип модуля наряду с JavaScript, CSS и изображениями. .wasm-файлы попадают в граф зависимостей и обрабатываются через систему трансформаций и кэширования, что позволяет включать бинарные модули без ручной настройки загрузчиков.

WebAssembly в Parcel работает через унифицированный механизм ресурсов: файл анализируется, оптимизируется, получает хешированное имя и помещается в итоговый бандл как отдельный ассет. На этапе выполнения он загружается через стандартный WebAssembly API или через обёртки, генерируемые сборщиком.


Базовый импорт .wasm как модуля

Parcel поддерживает прямой импорт WebAssembly-модулей:

import wasmUrl from "./module.wasm";

В этом случае результатом импорта становится URL до собранного .wasm-файла. Такой подход используется, когда требуется вручную управлять загрузкой:

const response = await fetch(wasmUrl);
const buffer = await response.arrayBuffer();
const module = await WebAssembly.instantiate(buffer, importObject);

export const instance = module.instance;

Parcel при этом выполняет:

  • копирование .wasm в выходной каталог
  • хеширование имени файла
  • оптимизацию доставки через dev/prod режимы

Автоматическая инициализация WebAssembly

Возможен импорт, при котором Parcel генерирует готовую инициализацию модуля:

import init, { add } from "./math.wasm";

await init();

console.log(add(2, 3));

В таком режиме сборщик:

  • создаёт JS-обёртку для загрузки WASM
  • автоматически вызывает WebAssembly.instantiateStreaming, если поддерживается
  • синхронизирует экспорты WASM с JavaScript API

Такой вариант характерен для модулей, собранных через Rust (wasm-bindgen) или AssemblyScript.


Статическая загрузка через URL import

Parcel позволяет работать с WebAssembly как с ассетом:

import wasmURL from "./module.wasm?url";

Поведение:

  • возвращается строка URL
  • модуль не инициализируется автоматически
  • загрузка контролируется вручную

Этот вариант применяется при необходимости:

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

Динамический импорт WebAssembly

WebAssembly может быть загружен через import():

const wasmModule = await import("./module.wasm");

await wasmModule.default();

Parcel в этом случае:

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

Динамическая загрузка особенно эффективна для:

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

Интеграция с Rust и wasm-bindgen

Наиболее распространённый сценарий — использование Rust через wasm-pack. Parcel корректно обрабатывает выходные артефакты:

import init, { calculate } from "./pkg/math_bg.wasm";

await init();

console.log(calculate(10));

Структура пакета обычно включает:

  • .wasm бинарник
  • JS glue-код
  • .d.ts (в TypeScript проектах)

Parcel сохраняет связность этих файлов и не разрывает их при бандлинге.


Работа с памятью и передачей данных

WebAssembly в Parcel не абстрагирует модель памяти. Передача данных остаётся явной:

const arr = new Uint32Array(instance.exports.memory.buffer);

arr[0] = 42;

const result = instance.exports.process(0);

Особенности:

  • память WASM остаётся в пределах WebAssembly.Memory
  • Parcel не вмешивается в layout памяти
  • взаимодействие происходит через TypedArray

Оптимизация загрузки и streaming compilation

Parcel использует возможности браузера:

  • WebAssembly.instantiateStreaming — при загрузке через HTTP
  • fallback на ArrayBuffer при несовместимости
  • предварительное кеширование в dev режиме

Условная схема:

const module = await WebAssembly.instantiateStreaming(fetch(url));

При этом Parcel гарантирует:

  • корректный MIME type (application/wasm)
  • отсутствие лишних преобразований бинарника
  • сохранение целостности файла при HMR

WebAssembly в связке с воркерами

WASM часто используется внутри Web Workers:

// worker.js
import wasmURL from "./compute.wasm";

const module = await WebAssembly.instantiateStreaming(fetch(wasmURL));

Parcel обеспечивает:

  • отдельный бандл для worker-контекста
  • изоляцию зависимостей
  • независимую загрузку WASM

Сценарии применения:

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

Кэширование и хеширование бинарных модулей

Parcel включает WebAssembly в систему контент-хеширования:

  • файл .wasm получает уникальное имя вида module.8f3a1c.wasm
  • изменения в бинарнике инвалидируют кэш
  • браузер может эффективно переиспользовать кешированные версии

Это снижает:

  • повторную загрузку
  • время cold start
  • нагрузку на сеть

Обработка ошибок загрузки и исполнения

Основные категории ошибок:

Ошибки компиляции

Возникают при:

  • повреждённом бинарнике
  • несовместимой версии WASM

Ошибки инициализации

WebAssembly.instantiateStreaming(fetch(url))

Причины:

  • неверный MIME type
  • CORS ограничения
  • отсутствие поддержки streaming API

Runtime ошибки

  • переполнение памяти WASM
  • выход за границы буфера
  • несовместимость экспортов

Parcel не скрывает ошибки, но сохраняет stack trace и source mapping для JS-обвязки.


Совместимость и целевые платформы

Поддержка WebAssembly в Parcel ориентирована на современные среды:

  • Chrome / Edge / Firefox / Safari (последние версии)
  • Node.js с поддержкой WASM API
  • Edge runtime environments

Ограничения проявляются в:

  • старых браузерах без streaming compilation
  • окружениях без WebAssembly глобального объекта

Связь WebAssembly с системой модулей

WebAssembly в Parcel интегрируется с ESM-моделью:

  • .wasm рассматривается как модуль
  • экспортируется через JS wrapper
  • импортируется синхронно или асинхронно

Пример цепочки зависимостей:

main.js
  └── compute.wasm
        └── memory import object

Parcel строит единый dependency graph, где WASM не является изолированным ресурсом, а частью модульной системы приложения.