Package Exports
- lzma-web
- lzma-web/compress
- lzma-web/decompress
- lzma-web/sync
- lzma-web/worker
Readme
lzma-web
The fastest isomorphic LZMA compression library for JavaScript. Works in browsers, Electron, and Node.js with a tree-shakeable, Promise-based API and optional Web Worker support.
Features
- Multiple APIs - Promise-based, synchronous, and Web Worker APIs
- Tree-shakeable - Import only compression or decompression to reduce bundle size
- TypeScript - Full type definitions included
- Web Workers - Automatic off-main-thread compression in browsers
- Universal - Works in browsers, Electron, and Node.js
- Compatible - Output compatible with the reference LZMA implementation
Installation
# npm
npm install lzma-web
# yarn
yarn add lzma-web
# pnpm
pnpm add lzma-webQuick Start
import { compress, decompress } from 'lzma-web'
// Compress a string
const compressed = await compress('Hello, World!')
// Decompress back to original
const decompressed = await decompress(compressed)
console.log(decompressed) // 'Hello, World!'API Reference
Entry Points Overview
| Entry Point | Purpose | Best For |
|---|---|---|
lzma-web |
Default Promise-based API | General async usage |
lzma-web/sync |
Synchronous API | Node.js, small data, no async needed |
lzma-web/worker |
Web Worker API | Browser, keeping UI responsive |
lzma-web/compress |
Compression only | Bundle optimization (tree-shaking) |
lzma-web/decompress |
Decompression only | Bundle optimization (tree-shaking) |
Main API (lzma-web)
The default entry point provides Promise-based compression and decompression.
import { compress, decompress } from 'lzma-web'
// Compress with default settings (mode 9)
const compressed = await compress('Hello, World!')
// Compress with specific compression level (1-9)
const fastCompressed = await compress('Hello, World!', 1)
// Decompress
const decompressed = await decompress(compressed)Compression Levels
The second argument to compress controls the compression level (1–9). Higher levels compress more but take longer.
| Level | Memory Usage | Speed | Ratio |
|---|---|---|---|
| 1 | ~1 MB | Fastest | ~40% |
| 2 | ~2 MB | Very Fast | ~42% |
| 3 | ~4 MB | Fast | ~45% |
| 4 | ~8 MB | Medium-Fast | ~48% |
| 5 | ~16 MB | Medium | ~50% |
| 6 | ~32 MB | Medium-Slow | ~52% |
| 7 | ~48 MB | Slow | ~53% |
| 8 | ~64 MB | Very Slow | ~54% |
| 9 | ~64 MB | Slowest | ~55% |
Default is 9 (best compression). Ratios are approximate and vary based on input data.
With Progress Callbacks
import { compress, decompress } from 'lzma-web'
// Compression with progress
const compressed = await compress(
largeData,
9,
(progress) => {
console.log(`Compressing: ${(progress * 100).toFixed(1)}%`)
}
)
// Decompression with progress
const decompressed = await decompress(
compressed,
(progress) => {
// progress is 0-1 for known size, or -1 if size is unknown
if (progress >= 0) {
console.log(`Decompressing: ${(progress * 100).toFixed(1)}%`)
}
}
)Synchronous API (lzma-web/sync)
For blocking operations when you don't need async behavior.
import { compressSync, decompressSync } from 'lzma-web/sync'
// Compress synchronously
const compressed = compressSync('Hello, World!', 1)
// Decompress synchronously
const decompressed = decompressSync(compressed)Note: Synchronous operations block the main thread. Use for small data or in Node.js environments where blocking is acceptable.
Web Worker API (lzma-web/worker)
Explicitly manage Web Worker lifecycle for browser applications.
import { createWorkerLZMA } from 'lzma-web/worker'
// Create a worker instance
const lzma = createWorkerLZMA()
// Compress (runs in Web Worker)
const compressed = await lzma.compress('Hello, World!', 9)
// Decompress (runs in Web Worker)
const decompressed = await lzma.decompress(compressed)
// Clean up when done (important!)
lzma.terminate()Note: The Worker is created lazily on first operation. Call
terminate()to clean up resources when you're done.
Tree-Shaking Modules
For bundle size optimization, import only what you need.
Compression Only (lzma-web/compress)
import { compress, compressSync, compressAsync } from 'lzma-web/compress'
// Async compression (callback internally handled)
const compressed = await compress('Hello, World!', 5)
// Sync compression (blocking)
const compressedSync = compressSync('Hello, World!', 5)
// Async with progress callback
const compressedWithProgress = await compressAsync('Hello, World!', 5, (p) => {
console.log(`Progress: ${p * 100}%`)
})Decompression Only (lzma-web/decompress)
import { decompress, decompressSync, decompressAsync } from 'lzma-web/decompress'
// Async decompression
const decompressed = await decompress(compressedData)
// Sync decompression (blocking)
const decompressedSync = decompressSync(compressedData)
// Async with progress callback
const decompressedWithProgress = await decompressAsync(compressedData, (p) => {
console.log(`Progress: ${p >= 0 ? p * 100 + '%' : 'unknown'}`)
})Tip: Use these modules when you only need one operation. This significantly reduces bundle size through tree-shaking.
Web Workers
How It Works
The main lzma-web API automatically uses Web Workers in browsers to prevent blocking the UI thread. Workers are initialized lazily on first use.
Fallback Behavior
- Browser with Web Workers: Operations run in a background thread
- Browser without Web Workers: Falls back to main thread (blocking)
- Node.js: Runs in main thread (no Worker support)
Manual Worker Management
Use lzma-web/worker when you need explicit control:
import { createWorkerLZMA } from 'lzma-web/worker'
// Each call creates a new Worker
const worker1 = createWorkerLZMA()
const worker2 = createWorkerLZMA()
// Run operations in parallel
const [result1, result2] = await Promise.all([
worker1.compress(data1, 5),
worker2.compress(data2, 5),
])
// Clean up
worker1.terminate()
worker2.terminate()Bundle Size Optimization
Choose the right entry point for your use case:
| Entry Point | Use Case | Bundle Impact |
|---|---|---|
lzma-web |
Need both compress & decompress | Full library |
lzma-web/compress |
Only compressing data | ~50% smaller |
lzma-web/decompress |
Only decompressing data | ~50% smaller |
lzma-web/sync |
Synchronous operations only | Similar to main |
Example for a client that only decompresses server-compressed data:
// Only imports decompression code - smaller bundle!
import { decompress } from 'lzma-web/decompress'
const data = await decompress(serverResponse)Performance
As of March 2026, lzma-web is the fastest isomorphic (browser + Electron + Node.js) LZMA library we could find. It consistently outperforms other pure-JS implementations by 2–5x across compression and decompression workloads.
| Library | Type | Small text compress | Large text (~4 MB) compress | Small text decompress |
|---|---|---|---|---|
| lzma-web | JS (isomorphic) | 71.8 ops/s | 0.30 hz | 380.6 ops/s |
@sarakusha/lzma |
JS (isomorphic) | 33.3 ops/s | 0.19 hz | 190.3 ops/s |
lzma1 |
JS (isomorphic) | 25.6 ops/s | 0.06 hz | 163.7 ops/s |
@napi-rs/lzma |
Rust (Node.js only) | 1,195 ops/s | 10.9 hz | 1,930 ops/s |
lzma-native |
C++ (Node.js only) | 334 ops/s | 0.68 hz | 2,727 ops/s |
All JS libraries benchmarked at compression level 1. Native solutions like @napi-rs/lzma and lzma-native are significantly faster in Node.js, but they require native binaries and don't run in the browser.
# Run the comparison benchmarks yourself
pnpm test:benchLicense
MIT — originally forked from LZMA-JS by Nathan Rugg.