WebAssembly (WASM) предоставляет возможность запускать бинарный код в среде JavaScript с высокой производительностью. Deno, современный runtime для JavaScript и TypeScript, обеспечивает удобную интеграцию WASM модулей, позволяя использовать их как в серверной, так и в клиентской логике.
Для загрузки WASM модуля используется стандартный API
WebAssembly. В Deno модуль можно загрузить из файла или из
URL:
const wasmCode = await Deno.readFile("./module.wasm");
const wasmModule = await WebAssembly.instantiate(wasmCode);
Здесь Deno.readFile возвращает Uint8Array,
который передается в WebAssembly.instantiate. Результатом
является объект с экспортами модуля, доступный через
wasmModule.instance.exports.
Для загрузки модуля по URL применяется fetch:
const response = await fetch("https://example.com/module.wasm");
const wasmArrayBuffer = await response.arrayBuffer();
const wasmModule = await WebAssembly.instantiate(wasmArrayBuffer);
Это позволяет динамически загружать WASM модули с удалённых ресурсов, что особенно удобно для микросервисной архитектуры.
WASM модули могут экспортировать функции, которые вызываются из JavaScript/TypeScript:
const { add, multiply } = wasmModule.instance.exports as {
add: (a: number, b: number) => number;
multiply: (a: number, b: number) => number;
};
console.log(add(5, 3)); // 8
console.log(multiply(4, 7)); // 28
Для доступа к памяти модуля используется объект
WebAssembly.Memory:
const memory = new WebAssembly.Memory({ initial: 1 }); // 64KiB страницы
Этот объект можно передавать в модуль через секцию
imports:
const imports = {
env: {
memory,
log: (value: number) => console.log(value),
},
};
const wasmModule = await WebAssembly.instantiate(wasmArrayBuffer, imports);
Память WASM представлена как линейный массив байтов
(ArrayBuffer). Для взаимодействия с ней удобно использовать
типизированные массивы:
const memoryBuffer = new Uint8Array(memory.buffer);
memoryBuffer[0] = 42;
Для чтения и записи структурированных данных применяются типы
Int32Array, Float64Array и другие. Это
позволяет эффективно передавать данные между JavaScript и WASM без
лишнего копирования.
Deno поддерживает асинхронную инициализацию WASM модулей, что важно для модулей с большим размером или при загрузке через сеть:
const wasmModule = await WebAssembly.instantiateStreaming(fetch("./module.wasm"));
Метод instantiateStreaming экономит память и ускоряет
загрузку, так как декодирование и компиляция выполняются по мере
получения байт.
Fresh — это современный фреймворк для рендеринга на сервере и клиенте. WASM модули могут использоваться для оптимизации вычислений в компонентах Fresh. Например, сложные вычисления или алгоритмы обработки данных можно вынести в WASM, снижая нагрузку на JavaScript-слой:
/** routes/data.ts */
import { Handlers } from "$fresh/server.ts";
import wasmModuleUrl from "../wasm/calc.wasm?url";
const wasmModule = await WebAssembly.instantiateStreaming(fetch(wasmModuleUrl));
export const handler: Handlers = {
async GET(req) {
const { compute } = wasmModule.instance.exports as { compute: (x: number) => number };
const result = compute(10);
return new Response(JSON.stringify({ result }), { status: 200 });
},
};
Такой подход обеспечивает высокую производительность и чистую архитектуру, где сложная логика отделена от UI.
Для удобства работы с экспортами WASM модулей рекомендуется описывать типы функций в TypeScript. Это повышает безопасность и облегчает отладку:
interface WasmExports {
add(a: number, b: number): number;
multiply(a: number, b: number): number;
}
const { add, multiply } = wasmModule.instance.exports as WasmExports;
WebAssembly.instantiateStreaming для
загрузки больших модулей.WASM в Deno открывает возможности высокой производительности и безопасного взаимодействия с низкоуровневым кодом. С его помощью можно создавать сложные вычислительные модули для Fresh, сохраняя чистоту архитектуры и скорость работы приложения.