GithubHelp home page GithubHelp logo

rosswilliams / brotli-wasm Goto Github PK

View Code? Open in Web Editor NEW

This project forked from httptoolkit/brotli-wasm

0.0 1.0 0.0 73 KB

A reliable compressor and decompressor for Brotli, supporting node & browsers via wasm

License: Apache License 2.0

JavaScript 17.25% Rust 36.09% TypeScript 46.66%

brotli-wasm's Introduction

brotli-wasm Build Status Available on NPM

Part of HTTP Toolkit: powerful tools for building, testing & debugging HTTP(S)

A reliable compressor and decompressor for Brotli, supporting node & browsers via wasm

Brotli is available in modern Node (12+) but not older Node or browsers. With this package, you can immediately use it everywhere.

This package contains a tiny wrapper around the compress & decompress API of the Rust Brotli crate, compiled to wasm with just enough setup to make it easily usable from JavaScript.

This is battle-tested, in production use in both node & browsers as part of HTTP Toolkit, and includes automated build with node & browser tests to make sure.

Getting started

npm install brotli-wasm

You should be able to import this directly into Node, as normal, or in a browser using any bundler that supports ES modules & webassembly (e.g. Webpack v4 or v5, Vite, Rollup, and most others).

For each target (node.js, commonjs bundlers & ESM bundlers) this module exports a different WASM file & setup, with a slightly different entrypoint. These entrypoints all expose a consistent default-export API, in addition to some other exports that may vary (e.g. Node exposes the brotli methods synchronously, while browsers always require an await due to WASM limitations).

In all builds (after waiting for the exported promise in browsers) the module exposes two core methods:

  • compress(Buffer, [options]) - compresses a buffer using Brotli, returning the compressed buffer. An optional options object can be provided. The only currently supported option is quality: a number between 1 and 11.
  • decompress(Buffer) - decompresses a buffer using Brotli, returning the original raw data.

For advanced use data-streaming use cases, CompressStream and DecompressStream classes for streaming compression are also available. See the tests for example usage.

Usage

If you want to support node & browsers with the same code, you can use the await browser-compatible form with the default export everywhere.

In node.js:

const brotli = require('brotli-wasm');

const compressedData = brotli.compress(Buffer.from('some input'));
const decompressedData = brotli.decompress(compressedData);

console.log(Buffer.from(decompressedData).toString('utf8')); // Prints 'some input'

In browsers:

import brotliPromise from 'brotli-wasm'; // Import the default export

const brotli = await brotliPromise; // Import is async in browsers due to wasm requirements!

const textEncoder = new TextEncoder();
const textDecoder = new TextDecoder();

const input = 'some input';

const uncompressedData = textEncoder.encode('some input');
const compressedData = brotli.compress(uncompressedData);
const decompressedData = brotli.decompress(compressedData);

console.log(textDecoder.decode(decompressedData)); // Prints 'some input'

The package itself has no runtime dependencies, although if you prefer using Buffer over using TextEncoder/TextDecoder you may want a browser Buffer polyfill.

In browser with streams:

import brotliPromise from 'brotli-wasm'; // Import the default export

const brotli = await brotliPromise; // Import is async in browsers due to wasm requirements!

const input = 'some input';

const inputStream = new ReadableStream({
    start (controller) {
        controller.enqueue(input);
        controller.close();
    }
});

const textEncoderStream = new TextEncoderStream();
const compressStream = new brotli.CompressStream();
const compressionStream = new TransformStream({
    start () {},
    transform (chunk, controller) {
        controller.enqueue(compressStream.compress(chunk, 100));
    },
    flush (controller) {
        if (compressStream.result() === brotli.BrotliStreamResult.NeedsMoreInput) {
            controller.enqueue(compressStream.compress(undefined, 100));
        }
        controller.terminate();
    }
});

const decompressStream = new brotli.DecompressStream();
const decompressionStream = new TransformStream({
    start () {},
    transform (chunk, controller) {
        controller.enqueue(decompressStream.decompress(chunk, 100));
    },
    flush (controller) {
        if (decompressStream.result() === brotli.BrotliStreamResult.NeedsMoreInput) {
            controller.enqueue(decompressStream.decompress(undefined, 100));
        }
        controller.terminate();
    }
});

const textDecoderStream = new TextDecoderStream()
const outputStream = new WritableStream({
    write (chunk) {
        output += chunk;
    }
});

let output = '';
await inputStream
    .pipeThrough(textEncoderStream)
    .pipeThrough(compressionStream)
    .pipeThrough(decompressionStream)
    .pipeThrough(textDecoderStream)
    .pipeTo(outputStream);
console.log(output); // Prints 'some input'

Note that TransformStream has become available in all browsers as of mid-2022. https://caniuse.com/mdn-api_transformstream

Alternatives

There's a few other packages that do similar things, but I found they were all unusable and/or unmaintained:

  • brotli-dec-wasm - decompressor only, compiled from Rust just like this package, actively maintained, but no compressor available (by design). If you only need decompression, this package is a good choice.
  • Brotli.js - hand-written JS decompressor that seems to work OK for most cases, but it crashes for some edge cases and the emscripten build of the compressor doesn't work in browsers at all. Last updated in 2017.
  • wasm-brotli - Compiled from Rust like this package, includes decompressor & compressor, but requires a custom async wrapper for Webpack v4 usage and isn't usable at all in Webpack v5. Last updated in 2019.

brotli-wasm's People

Contributors

pimterry avatar myl7 avatar jonluca avatar httnn avatar willfarrell avatar stefnotch avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.