Runtimes
The same JavaScript runs on every runtime; what changes is the build target and which runtime features exist there. This page is the map: what to build, how to load it, and what is unavailable before you find out the hard way.
What each runtime supports
| Runtime | Output | Threads (mt) | useWorker | Persistent storage |
|---|---|---|---|---|
| Browser | wasm + JS loader | yes, needs COOP/COEP | yes | OPFS, with useWorker: true |
| Node.js | wasm + JS loader | yes | no (n/a) | the host filesystem |
| Cloudflare Workers / edge | wasm + JS loader | no | no | no - external store only |
| React Native | native .a / xcframework over JSI | yes, no headers needed | n/a | the app sandbox |
| WASI | one .wasm command | no (single-threaded for now) | n/a | preopened host dirs |
Threading and useWorker are two independent axes, and the difference bites often enough to have its own page: Threading and workers.
Target flags
A build target is a {platform, arch, runtime, runtimeEnv, buildType} tuple. With a bundler plugin the tuple is chosen for you; from the CLI you filter it with flags.
| Flag | Values |
|---|---|
-p platform | wasm, wasi, android, ios |
-a arch | wasm32, wasm64, arm64-v8a, x86_64, iphoneos, iphonesimulator |
-r runtime | st, mt |
-e runtimeEnv | browser, node, edge |
-b buildType | release, debug |
Browser
The default. Install the plugin for your bundler, import the header, call initNative(). Two browser-only options matter:
With useWorker: true every call crosses a worker boundary and therefore returns a promise - including construction (await new X()). Files then live in the filesystem you mounted.
Node.js
Build with -e node and import the generated loader. m.FS reads and writes the real host filesystem, so there is no /opfs versus /memfs distinction.
CommonJS works the same way with require(...). Environment variables for the wasm process go through init's env option, where _CPPJS_DATA_PATH_ expands to the runtime data path.
Cloudflare Workers and the edge
Edge runtimes are V8 isolates with no Web Worker API, so useWorker and runtime: 'mt' are both unavailable - build -e edge -r st. Bundle the wasm and hand it to initNative directly, which avoids a network round-trip at cold start.
m.FS.writeFile(...).React Native and Expo
Mobile compiles to real native code and reaches JavaScript through JSI - no wasm, no SharedArrayBuffer, no COOP/COEP. runtime: 'mt' works with no host configuration. Wire Metro as shown in Bundlers, then call into the header from a component:
Expo
Expo Go cannot load custom native code, so switch to a development build first, then add the config plugin - it wires the native build during expo prebuild.
iOS also needs pod install inside ios/ before the first npm run ios.
WASI
With -p wasi there is no JavaScript host at all: the output is a single wasm32-wasip3 command you run under wasmtime. Prebuilt CLI tools ship the same way as npm packages. Full details in WASI commands.