WebAssembly (WASM) используется в JavaScript-проектах для выполнения
высокопроизводительного кода, написанного на Rust, C/C++ и других
языках, компилируемых в бинарный формат. В сборщике Rollup поддержка
WASM реализуется через плагин @rollup/plugin-wasm, который
обеспечивает корректную интеграцию .wasm модулей в итоговый
бандл и управление их загрузкой.
Основная задача плагина заключается в преобразовании импортов WebAssembly-файлов в JavaScript-код, который может корректно загружать, компилировать и инициализировать WASM-модуль во время выполнения.
Плагин @rollup/plugin-wasm работает на этапе
трансформации модулей Rollup. При обнаружении импорта .wasm
файла он:
Ключевая особенность заключается в выборе стратегии включения WASM:
fetch и
WebAssembly.instantiateStreamingПлагин устанавливается как обычная зависимость проекта:
npm install @rollup/plugin-wasm --save-dev
Подключение в конфигурации Rollup:
import wasm from '@rollup/plugin-wasm';
export default {
input: 'src/index.js',
output: {
format: 'esm',
dir: 'dist'
},
plugins: [
wasm()
]
};
После подключения Rollup начинает распознавать .wasm
импорты как модули.
Структура проекта:
src/
index.js
math.wasm
Импорт WASM в Jav * aScript:
import initWasm from './math.wasm';
const wasmModule = await initWasm();
console.log(wasmModule.exports.add(2, 3));
Плагин генерирует функцию инициализации, которая возвращает объект
exports, содержащий экспортированные функции
WASM-модуля.
Плагин поддерживает несколько стратегий интеграции WASM.
WASM-код встраивается напрямую в JavaScript-бандл в виде бинарного массива.
wasm({
mode: 'inline'
});
Характеристики:
WASM выносится в отдельный файл, который загружается динамически.
wasm({
mode: 'url'
});
Поведение:
.wasm файл в output директорииfetchwasm({
mode: 'fetch'
});
Особенности:
WebAssembly.instantiateStreamingapplication/wasmНаиболее корректный сценарий использования WASM. Поддерживается
динамическая загрузка через import() и
await.
export default async function load() {
const wasm = await import('./module.wasm');
return wasm.default();
}
В CommonJS форматах плагин эмулирует асинхронную загрузку:
const wasm = require('./module.wasm');
wasm().then(instance => {
console.log(instance.exports);
});
Такой режим может приводить к усложнению управления асинхронностью.
WebAssembly-модули могут экспортировать функции, память и таблицы.
Пример Rust-кода:
#[no_mangle]
pub fn multiply(a: i32, b: i32) -> i32 {
a * b
}
В JavaScript после подключения через Rollup:
import init from './math.wasm';
const wasm = await init();
console.log(wasm.exports.multiply(4, 5));
Экспортируемая структура зависит от компилятора и упаковщика WASM.
WASM использует линейную память, которая может быть доступна в
JavaScript через WebAssembly.Memory.
Пример работы с буфером:
const wasm = await init();
const memory = wasm.exports.memory;
const view = new Uint8Array(memory.buffer);
view[0] = 42;
Rollup не изменяет модель памяти, но обеспечивает корректную упаковку и загрузку модуля.
При использовании @rollup/plugin-wasm важны следующие
аспекты:
Inline режим увеличивает размер JavaScript-бандла, поэтому используется для:
URL режим позволяет браузеру кэшировать .wasm файл
отдельно от JS.
Использование динамического import() позволяет загружать
WASM только при необходимости:
button.addEventListener('click', async () => {
const wasm = await import('./heavy.wasm');
wasm.default();
});
WASM почти всегда требует async-обёртки, что влияет на архитектуру приложения.
Для корректной работы instantiateStreaming сервер должен
отдавать:
Content-Type: application/wasm
WASM-модули не поддаются классическому tree-shaking, так как являются бинарными артефактами.
В старых браузерах может отсутствовать:
В таких случаях используется fallback через
ArrayBuffer.
При использовании TypeScript требуется декларация модуля:
declare module '*.wasm' {
const initWasm: () => Promise<any>;
export default initWasm;
}
Rollup не генерирует типы автоматически, поэтому типизация задается вручную.
@rollup/plugin-wasm часто используется совместно с:
@rollup/plugin-node-resolve — для резолва
зависимостей@rollup/plugin-commonjs — для поддержки CJS
окруженийrollup-plugin-terser — для минификации итогового
JSПорядок подключения плагинов влияет на поведение загрузки WASM:
plugins: [
nodeResolve(),
wasm(),
terser()
]
При диагностике проблем важно учитывать:
.wasmЧасто используемый подход — временное переключение режима:
wasm({
mode: 'url'
});
Это позволяет изолировать проблемы загрузки от проблем инлайна.
WASM в Rollup чаще всего применяется в следующих областях:
Rollup обеспечивает минимальную обвязку вокруг WASM, сохраняя производительность близкой к нативной.
После сборки Rollup с @rollup/plugin-wasm итоговый код
обычно включает:
.wasm файлinstantiate или
instantiateStreamingЭто позволяет интегрировать WASM в любой модульный JavaScript-код без ручной настройки низкоуровневых API WebAssembly