JavaScript Compression Streams API Gzip Guide

The Compression Streams API is a native web API that enables JavaScript to compress and decompress data streams directly in the browser or supported runtime environments without external libraries. This article explores how the Compression Streams API works and provides practical code examples demonstrating how to compress and decompress raw data using standard gzip compression.

What is the Compression Streams API?

The Compression Streams API provides built-in browser primitives for data compression using standard stream interfaces. Traditionally, client-side data compression required third-party JavaScript libraries such as Pako. With the Compression Streams API, compression is handled natively by the browser engine, resulting in smaller bundle sizes and improved execution performance.

The API exposes two core interfaces:

Compressing Raw Data with Gzip

To compress data, the raw input—typically a string or binary buffer—is converted into a ReadableStream, piped through an instance of CompressionStream('gzip'), and consumed as compressed binary output.

Here is a step-by-step example compressing a plain text string into a gzip-compressed Uint8Array:

async function compressData(inputString) {
  // 1. Convert the string into a Uint8Array
  const textEncoder = new TextEncoder();
  const rawBytes = textEncoder.encode(inputString);

  // 2. Create a stream from the raw bytes
  const byteStream = new ReadableStream({
    start(controller) {
      controller.enqueue(rawBytes);
      controller.close();
    }
  });

  // 3. Initialize the gzip compression stream
  const compressionStream = new CompressionStream('gzip');

  // 4. Pipe the byte stream through the compression stream
  const compressedStream = byteStream.pipeThrough(compressionStream);

  // 5. Convert the stream output to an ArrayBuffer using the Response API
  const compressedBuffer = await new Response(compressedStream).arrayBuffer();

  return new Uint8Array(compressedBuffer);
}

Explanation of the Steps

  1. Text Encoding: The TextEncoder translates the human-readable string into a stream-compatible Uint8Array.
  2. Stream Creation: A ReadableStream is initialized to feed the encoded binary data into the pipeline.
  3. CompressionStream Initialization: Calling new CompressionStream('gzip') specifies the target format.
  4. Piping: The pipeThrough() method forwards raw chunks into the compressor, which continuously yields compressed chunks.
  5. Response Consumption: Wrapping the resulting stream inside a Response object allows the use of .arrayBuffer(), which reads the entire stream until completion and returns the final compressed buffer.

Decompressing Gzip Data

Decompressing data follows the inverse process using DecompressionStream:

async function decompressData(compressedBytes) {
  // 1. Create a readable stream from the compressed byte array
  const byteStream = new ReadableStream({
    start(controller) {
      controller.enqueue(compressedBytes);
      controller.close();
    }
  });

  // 2. Initialize the gzip decompression stream
  const decompressionStream = new DecompressionStream('gzip');

  // 3. Pipe compressed data through the decompressor
  const decompressedStream = byteStream.pipeThrough(decompressionStream);

  // 4. Read the stream as an ArrayBuffer and decode to string
  const decompressedBuffer = await new Response(decompressedStream).arrayBuffer();
  const textDecoder = new TextDecoder();

  return textDecoder.decode(decompressedBuffer);
}

Key Use Cases