Binaryen and wasm-opt
Binaryen is Google’s optimising compiler infrastructure for WebAssembly. Its most widely used tool is wasm-opt, which takes an existing .wasm binary and rewrites it to produce a smaller or faster output. You do not need to understand Binaryen’s internal IR to benefit from it — a single command can cut 20–40 % off a release binary.
What wasm-opt does
Section titled “What wasm-opt does”wasm-opt applies a sequence of compiler passes: dead-code elimination, constant folding, function inlining, local CSE, and many more. It works entirely on the binary level — it does not need the original source or any metadata.
# Install globally via npmnpm install -g binaryen
# Or install via Homebrew on macOSbrew install binaryenOptimisation levels
Section titled “Optimisation levels”wasm-opt uses the same level flags as Clang/GCC:
# -O1 — light optimisation (fast build)wasm-opt -O1 input.wasm -o output.wasm
# -O2 — balanced (same as release builds in most toolchains)wasm-opt -O2 input.wasm -o output.wasm
# -O3 — aggressive (maximise speed, larger code possible)wasm-opt -O3 input.wasm -o output.wasm
# -Os — optimise for size (speed is secondary)wasm-opt -Os input.wasm -o output.wasm
# -Oz — maximise size reduction (slowest optimisation)wasm-opt -Oz input.wasm -o output.wasmFor most production deployments, -Oz offers the best trade-off: smaller download, faster parse, warm cache.
Toolchains run it for you
Section titled “Toolchains run it for you”In practice you rarely call wasm-opt directly. These popular toolchains invoke it automatically in release mode:
| Toolchain | When it runs wasm-opt |
|---|---|
| Emscripten | -O2 / -O3 release flags |
| wasm-pack (Rust) | wasm-pack build --release |
| AssemblyScript | asc --optimize |
| Go (TinyGo) | -opt=z flag |
If you are consuming a .wasm from any of these, the binary is probably already optimised. Running wasm-opt a second time is safe but yields diminishing returns.
Additional useful flags
Section titled “Additional useful flags”# Strip the DWARF debug section (reduces size, loses stack traces)wasm-opt -Oz --strip-dwarf input.wasm -o output.wasm
# Strip all custom sectionswasm-opt -Oz --strip-producers input.wasm -o output.wasm
# Print module statistics before and afterwasm-opt -Oz --print-stats input.wasm -o output.wasm
# Keep a name section for readable stack traceswasm-opt -Oz --debuginfo input.wasm -o output.wasmMeasuring the effect
Section titled “Measuring the effect”Always measure before and after. A quick bash one-liner shows the size difference:
wasm-opt -Oz input.wasm -o output.wasmecho "Before: $(wc -c < input.wasm) bytes"echo "After: $(wc -c < output.wasm) bytes"