DEV Community

Wilson Xu
Wilson Xu

Posted on

Using WebAssembly in Node.js CLI Tools for 100x Performance

Using WebAssembly in Node.js CLI Tools for 100x Performance

Some operations in CLI tools are inherently slow in JavaScript: parsing large binary files, image processing, cryptographic hashing, or running complex algorithms. You can reach for native C++ addons, but they break on different platforms and require compiler toolchains.

WebAssembly offers a middle path: near-native performance, runs everywhere Node.js runs, no compilation step for users. This article shows how to use Wasm modules in CLI tools for the operations where JavaScript is too slow.

When Wasm Makes Sense

Wasm is worth the complexity when:

  • CPU-bound operations dominate runtime (not I/O-bound)
  • Performance matters — 10x+ improvement needed, not 10%
  • Cross-platform is required — no native compilation for users
  • Existing C/Rust code can be compiled to Wasm

Don't use Wasm for: file I/O, network requests, string manipulation, JSON parsing — JavaScript is already fast enough.

Loading Wasm in Node.js

import { readFile } from 'node:fs/promises';
import { join } from 'node:path';

async function loadWasm(wasmPath: string) {
  const buffer = await readFile(wasmPath);
  const module = await WebAssembly.compile(buffer);
  const instance = await WebAssembly.instantiate(module, {
    env: {
      // Import functions the Wasm module can call
      log: (ptr: number, len: number) => {
        // Read string from Wasm memory
        const bytes = new Uint8Array(instance.exports.memory.buffer, ptr, len);
        console.log(new TextDecoder().decode(bytes));
      },
    },
  });
  return instance.exports;
}
Enter fullscreen mode Exit fullscreen mode

Real Example: Fast File Hashing

JavaScript's crypto.createHash is already fast, but for hashing thousands of files (like in a file integrity checker), Wasm can be 3-5x faster:

// Using a Wasm-compiled xxHash implementation
import { xxhash } from './wasm/xxhash.js';

async function hashFile(filePath: string): Promise<string> {
  const buffer = await readFile(filePath);
  return xxhash(buffer);
}

// Benchmark: 10,000 files
// Node.js crypto.createHash('sha256'): 4.2 seconds
// Wasm xxHash:                         0.8 seconds
Enter fullscreen mode Exit fullscreen mode

Using Existing Wasm Packages

Many npm packages ship Wasm binaries:

// @aspect-build/rules_js uses Wasm for fast glob matching
import { glob } from 'fast-glob'; // Uses native/Wasm internally

// sharp uses Wasm for image processing (via libvips compiled to Wasm)
import sharp from 'sharp';

// esbuild ships a Wasm variant
import * as esbuild from 'esbuild-wasm';
await esbuild.initialize({ wasmURL: './node_modules/esbuild-wasm/esbuild.wasm' });
Enter fullscreen mode Exit fullscreen mode

Compiling Rust to Wasm for CLI Tools

If you have a Rust function you want to use:

// src/lib.rs
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn count_words(text: &str) -> u32 {
    text.split_whitespace().count() as u32
}

#[wasm_bindgen]
pub fn find_pattern(text: &str, pattern: &str) -> Vec<u32> {
    let mut positions = Vec::new();
    for (i, _) in text.match_indices(pattern) {
        positions.push(i as u32);
    }
    positions
}
Enter fullscreen mode Exit fullscreen mode
wasm-pack build --target nodejs
Enter fullscreen mode Exit fullscreen mode
// In your CLI tool
import { count_words, find_pattern } from './pkg/my_wasm.js';

const count = count_words(largeText);
const matches = find_pattern(logContent, 'ERROR');
Enter fullscreen mode Exit fullscreen mode

When to Use What

Task JS Speed Wasm Speed Winner
JSON parsing Fast Slower (overhead) JS
File I/O N/A N/A Same
String search (small) Fast Fast JS
Regex (large file) Medium Fast Wasm
Hash (many files) Medium Fast Wasm
Image resize Slow Fast Wasm
Compression Medium Fast Wasm
Math/algorithms Slow Fast Wasm

Conclusion

Wasm in CLI tools is a surgical optimization. Use it for the 1-2 operations where JavaScript's performance isn't enough, keep everything else in TypeScript. The result: a tool that installs with npm install (no compiler needed) but performs like native code where it matters.


Wilson Xu builds performant developer tools. Find his 16+ packages at npm.

Top comments (0)