JavaScript Compression Streams API: Native Gzip Guide

This article provides an overview of the Compression Streams API in modern JavaScript, explaining its purpose, browser support, and how to use it for native data compression. You will learn how this built-in web API replaces external compression libraries and how to implement native gzip compression and decompression directly in JavaScript using readable and writable streams.

What is the Compression Streams API?

The Compression Streams API is a built-in web standard interface designed to compress and decompress streams of data natively in JavaScript. Before its introduction, developers relied heavily on third-party libraries such as Pako or zlib ports to compress payloads in the browser, adding significant weight to JavaScript bundles.

The API provides two primary interfaces: - CompressionStream: A transform stream that compresses data. - DecompressionStream: A transform stream that decompresses compressed data.

Both interfaces support standard compression formats: - 'gzip': Compresses data using the gzip format (RFC 1952). - 'deflate': Compresses data using the zlib structure with the deflate algorithm (RFC 1950). - 'deflate-raw': Compresses data using the raw deflate algorithm without headers or checksums (RFC 1951).

How to Compress Data Using Native Gzip

To compress data natively, convert your input into a stream, pipe it through a CompressionStream('gzip') instance, and read the compressed bytes.

Here is a practical example of compressing a standard JavaScript string to a gzip-compressed Uint8Array:

async function compressData(inputString) {
  // Convert the input string to a Uint8Array byte stream
  const blob = new Blob([inputString]);
  const stream = blob.stream();

  // Pipe the stream through the gzip compression stream
  const compressedReadableStream = stream.pipeThrough(
    new CompressionStream('gzip')
  );

  // Read the compressed stream into an ArrayBuffer
  const response = new Response(compressedReadableStream);
  const arrayBuffer = await response.arrayBuffer();

  return new Uint8Array(arrayBuffer);
}

// Usage
const rawText = "This is a sample string that will be compressed using native gzip in JavaScript.";
compressData(rawText).then((compressedBytes) => {
  console.log("Compressed Bytes:", compressedBytes);
});

How to Decompress Gzip Data

Decompressing data follows the inverse process. You feed compressed binary data into a stream, pipe it through DecompressionStream('gzip'), and read the resulting raw output.

async function decompressData(compressedBytes) {
  // Convert binary compressed data into a stream
  const blob = new Blob([compressedBytes]);
  const stream = blob.stream();

  // Pipe the stream through the gzip decompression stream
  const decompressedStream = stream.pipeThrough(
    new DecompressionStream('gzip')
  );

  // Read the decompressed stream as text
  const response = new Response(decompressedStream);
  return await response.text();
}

// Usage
compressData(rawText).then((compressedBytes) => {
  decompressData(compressedBytes).then((decompressedText) => {
    console.log("Decompressed Text:", decompressedText);
  });
});

Key Benefits

  1. Zero Bundle Overhead: Since the API is built directly into modern runtimes, you eliminate the need for external compression dependencies.
  2. Stream-Friendly: The API handles large datasets efficiently chunk-by-chunk without loading the entire payload into memory simultaneously.
  3. Broad Support: The Compression Streams API is natively supported across all modern browsers (Chrome, Edge, Firefox, Safari) and server-side runtimes like Node.js (v18+) and Deno.