Zstandard for WebAssembly
v1.5.7WebAssemblyZstandard 1.5.7 for browsers, Node.js and edge runtimes, precompiled for wasm32, single-threaded and multi-threaded as @crossbind/port-zstd-wasm.
Install
crossbind itself arrives with your bundler plugin, or with a new project from npm create crossbind@beta; Bundlers has Vite, Webpack, Rspack and Rollup.
Usage
Each example runs here, in this tab, and prints what the site build checked.
Each example also has a JavaScript only tab: the same task with no C++ file, calling Zstandard's own headers from @crossbind/port-zstd directly. 3 of 4 work that way; the other says what stops it.
Compress and decompress a buffer
The two calls most zstd code makes: ZSTD_compress, and ZSTD_decompress with the original size read back from the frame.
The same two calls on zstd.h as zstd ships it. What the C++ did for you is now yours: size and allocate each buffer (allocBuffer memory is released with its handle), copy bytes in and out as one character per byte, and check every return with ZSTD_isError. ZSTD_getFrameContentSize returns an unsigned long long, so it arrives as a BigInt.
Stream a file through zstd
For data you should not hold in one buffer: ZSTD_compressStream2 and ZSTD_decompressStream work file to file in 128 KB steps.
ZSTD_compressStream2 reads and advances the src, size and pos fields of a ZSTD_inBuffer and a ZSTD_outBuffer. crossbind binds both structs as classes without fields, so what JavaScript sets never reaches zstd: the call returns 9 (bytes still to flush) and consumes nothing. The field-free ZSTD_compressStream2_simpleArgs is behind ZSTD_STATIC_LINKING_ONLY, which the bound zstd.h leaves undefined. Streaming takes the few lines of C++ in the other tab.Choose a level, a checksum and a window
A context set up with ZSTD_CCtx_setParameter decides what every frame it writes looks like; ZSTD_getFrameHeader reads the choices back.
Setting parameters and compressing work the same way; enum values cross one member at a time (await ZSTD_cParameter.ZSTD_c_windowLog). Reading the choices back does not: ZSTD_getFrameHeader is behind ZSTD_STATIC_LINKING_ONLY, so JavaScript gets the content size but not the window or the checksum flag.
Compress small messages with a dictionary
Train once with ZDICT_trainFromBuffer, digest it once with ZSTD_createCDict and ZSTD_createDDict, then compress every message against it.
ZDICT_trainFromBuffer takes the sample sizes as a size_t array, written here as little-endian 32-bit numbers because size_t is 4 bytes in wasm32 (8 on a 64-bit phone). Contexts and dictionaries are freed by hand.
What is different on WebAssembly
- In a browser the module runs in a Worker by default (
useWorker), so every call returns a promise:awaitcalls and constructors alike. - The module has its own filesystem:
m.FSwrites files,m.getFileBytesreads them back andm.autoMountFilesmountsFileobjects from an<input type=file>./memfslives in memory;/opfspersists across reloads and needs the Worker. See Filesystem. - In Node.js,
m.FSis the real disk, so use real paths there. - Multi-threaded builds (
runtime: 'mt') need COOP and COEP headers in production. See Threading.
Other platforms
- Zstandard overview: the apps, every platform's setup and the packages.
- Zstandard for Android: React Native apps on Android.
- Zstandard for iOS: React Native apps on iOS.
- Zstandard for WASI: command-line programs under wasmtime.
Facts on this page come from the port manifests in the repository and from what npm served on beta when the site was built. See the Libraries guide for the full consumer flow.