WebAssembly/Wasm
Cloudflare Workers supports running small WebAssembly modules within either script-based or module-based workers.
Denoflare provides a simple way to serve and deploy workers with WebAssembly components, building on Deno's built-in WebAssembly support .
Module-based workers
For module-based Cloudflare Workers, Cloudflare requires Wasm to be specified with an ES6 import of the form import module from "./hello.wasm"
(module
is then a
WebAssembly.Module
).
Since this is not valid in browsers/Deno, nor valid under the
proposed WebAssembly/ES Module Integration
, Denoflare needs to slighty modify the standard bundled module worker it uploads to Cloudflare during a denoflare push
.
It also needs to have syntax that will run in denoflare serve
in both local isolation modes, as well incorporate well into other Deno projects unrelated to Denoflare.
To accomplish this, Denoflare provides a special function called importWasm
that will load Wasm properly in Deno and both modes of denoflare serve
, and will be rewritten during denoflare push
to the syntax required by Cloudflare. importWasm
is just a
small standard Deno function
, it builds on
import.meta.url
and Deno's recent support for local file:// fetch
.
worker.ts
import { importWasm } from 'https://raw.githubusercontent.com/skymethod/denoflare/v0.6.0/common/import_wasm.ts';
const module = await importWasm(import.meta.url, './hello.wasm');
// import module from './hello.wasm';
// is the replacement used when pushing to Cloudflare
export default {
fetch(): Response {
try {
// call hello.wasm
const instance = new WebAssembly.Instance(module);
const result = (instance.exports.main as CallableFunction)();
const html = `<h3>Result from hello.wasm call: ${result}</h3>`;
return new Response(html, { status: 200, headers: { 'Content-Type': 'text/html; charset=utf-8' } });
} catch (e) {
const html = `${e}`;
return new Response(html, { status: 500, headers: { 'Content-Type': 'text/html; charset=utf-8' } });
}
}
};
See the hello-wasm-worker example for more information.
Script-based workers
For the older script-based Cloudflare Workers, WebAssembly modules are injected using global environment variable bindings .
Define your environment variable name and wasmModule
in the script's bindings
section in your .denoflare configuration file, then use the injected global variable at runtime, it will be a
WebAssembly.Module
.
worker.js
self.addEventListener('fetch', event => {
event.respondWith(safeHandleRequest(event));
});
async function safeHandleRequest(event) {
try {
// call hello.wasm
const instance = new WebAssembly.Instance(helloModule);
const result = instance.exports.main();
const html = `<h3>Result from hello.wasm call: ${result}</h3>`;
return new Response(html, { status: 200, headers: { 'Content-Type': 'text/html; charset=utf-8' } });
} catch (e) {
const html = `${e}`;
return new Response(html, { status: 500, headers: { 'Content-Type': 'text/html; charset=utf-8' } });
}
}
snippet from .denoflare config file
"wasm-script-worker": {
"path": "/path/to/worker.js",
"bindings": {
"helloModule": { "wasmModule": "/path/to/hello.wasm" },
}
}
More
- See Transform Images with Wasm for a larger example of using an existing Wasm library inside a worker.