zstandard_web
The web implementation of zstandard.
Installation
Copy zstd.js and zstd.wasm into your app's web/ folder. In this repo they are built into zstandard_web/blob/ and zstandard_web/example/web/ (see Generation below).
Include the library inside the <head>:
<!DOCTYPE html>
<html>
<head>
<script src="zstd.js"></script>
</head>
</html>
Usage
void act() async {
final zstandard = ZstandardWeb();
Uint8List original = Uint8List.fromList([...]);
Uint8List? compressed = await zstandard.compress(original);
Uint8List? decompressed = await zstandard.decompress(compressed ?? Uint8List(0));
}

Generation
The repo builds zstd.js and zstd.wasm from the same zstandard_native/src/zstd/ C source used by Android, iOS, macOS, Windows, Linux, and the CLI. From the repository root:
./scripts/build_web_wasm.sh
This script temporarily clones Emscripten SDK (emsdk), installs and activates the latest toolchain, compiles zstandard_native/src/zstd/ with emcc, appends the compressData/decompressData wrappers, and writes zstd.js and zstd.wasm to both zstandard_web/blob/ and zstandard_web/example/web/. Requires git and a shell; the emsdk directory is removed after the build.
Manual generation (optional)
If you prefer to build by hand (e.g. from upstream facebook/zstd or a custom emsdk install):
-
Install and activate Emscripten SDK:
git clone https://github.com/emscripten-core/emsdk.git cd emsdk ./emsdk install latest ./emsdk activate latest source ./emsdk_env.sh -
From the repo root (so the single source
zstd/is used), or from a clone of facebook/zstd (usinglib/in place ofzstd/), run:# If using this repo's zstandard_native (from repo root): cd zstandard_native/src/zstd emcc -O3 \ $(find common -name "*.c") \ $(find compress -name "*.c") \ $(find decompress -name "*.c") \ -I. -Icommon -Icompress -Idecompress \ -s WASM=1 \ -s EXPORT_NAME="zstdWasmModule" \ -s EXPORTED_FUNCTIONS="['_ZSTD_compress', '_ZSTD_decompress', '_malloc', '_free', '_ZSTD_getFrameContentSize', '_ZSTD_compressBound']" \ -o zstd.jsThen append the
compressDataanddecompressDatawrappers to the generatedzstd.js(see below), and copyzstd.jsandzstd.wasminto bothzstandard_web/blob/andzstandard_web/example/web/.
Add these methods to zstd.js (the script does this automatically):
function compressData(inputData, compressionLevel) {
let inputPtr = Module._malloc(inputData.length);
Module.HEAPU8.set(inputData, inputPtr);
let outputBufferSize = Module._ZSTD_compressBound(inputData.length);
let outputPtr = Module._malloc(outputBufferSize);
let compressedSize = Module._ZSTD_compress(
outputPtr,
outputBufferSize,
inputPtr,
inputData.length,
compressionLevel
);
if (compressedSize < 0) {
console.error('Compression error, error code: ', compressedSize);
return null;
} else {
let compressedData = new Uint8Array(Module.HEAPU8.buffer, outputPtr, compressedSize);
Module._free(inputPtr);
Module._free(outputPtr);
return compressedData;
}
}
function decompressData(compressedData) {
let compressedPtr = Module._malloc(compressedData.length);
Module.HEAPU8.set(compressedData, compressedPtr);
let decompressedSize = Module._ZSTD_getFrameContentSize(compressedPtr, compressedData.length);
if (decompressedSize === -1 || decompressedSize === -2) {
console.error('Error in obtaining the original size of the data');
Module._free(compressedPtr);
return null;
}
let decompressedPtr = Module._malloc(decompressedSize);
let resultSize = Module._ZSTD_decompress(
decompressedPtr,
decompressedSize,
compressedPtr,
compressedData.length
);
if (resultSize < 0) {
console.error('Decompression error, error code: ', resultSize);
Module._free(compressedPtr);
Module._free(decompressedPtr);
return null;
} else {
let decompressedData = new Uint8Array(Module.HEAPU8.buffer, decompressedPtr, resultSize);
Module._free(compressedPtr);
Module._free(decompressedPtr);
return decompressedData;
}
}
API
- ZstandardWeb() — Creates the web platform implementation.
- compress(Uint8List data, int compressionLevel) — Compresses
data(level 1–22). Returns compressed bytes or throws on failure. Inputs smaller than 9 bytes may be returned unchanged. - decompress(Uint8List data) — Decompresses zstd-compressed data. Returns decompressed bytes or throws on failure.
- getPlatformVersion() — Returns the browser user agent string.
Architecture
This package uses JavaScript interop and WebAssembly. It calls the global compressData and decompressData functions provided by zstd.js, which in turn use the compiled zstd C library in zstd.wasm. No Dart FFI; runs on the main thread.
Testing
From the package directory:
flutter test
Unit tests run only on web (skipped on other platforms). Full integration tests are in example/integration_test/ and require a browser (e.g. flutter test integration_test/ -d chrome).
Troubleshooting
- compressData / decompressData is not defined: Ensure
zstd.jsis included in yourweb/index.htmland loads before the Flutter app. - WASM load failed: Ensure
zstd.wasmis served from the same origin and the path is correct. Check the browser console and network tab.
See the documentation for more.