brotli-compress
Advanced tools
Comparing version
36
build.ts
@@ -57,6 +57,9 @@ import { build } from 'esbuild' | ||
// WASM compress + decompress | ||
build({ | ||
entryPoints: ['src/index.ts'], | ||
entryPoints: ['src/wasm.ts'], | ||
bundle: true, | ||
format: 'cjs', | ||
minify: true, | ||
target: 'es2020', | ||
@@ -71,7 +74,36 @@ outfile: 'index.js', | ||
build({ | ||
entryPoints: ['src/index.ts'], | ||
entryPoints: ['src/wasm.ts'], | ||
bundle: true, | ||
target: 'es2020', | ||
format: 'esm', | ||
minify: true, | ||
outfile: 'index.mjs', | ||
plugins: [wasmPlugin], | ||
}).catch((e) => { | ||
console.error(e) | ||
process.exit(1) | ||
}) | ||
// JS decompress | ||
build({ | ||
entryPoints: ['src/js.ts'], | ||
bundle: true, | ||
format: 'cjs', | ||
target: 'es2020', | ||
minify: true, | ||
outfile: 'js.js', | ||
plugins: [wasmPlugin], | ||
}).catch((e) => { | ||
console.error(e) | ||
process.exit(1) | ||
}) | ||
build({ | ||
entryPoints: ['src/js.ts'], | ||
bundle: true, | ||
target: 'es2020', | ||
minify: true, | ||
format: 'esm', | ||
outfile: 'js.mjs', | ||
// | ||
@@ -78,0 +110,0 @@ plugins: [wasmPlugin], |
{ | ||
"name": "brotli-compress", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"main": "index.js", | ||
@@ -39,4 +39,3 @@ "module": "index.mjs", | ||
"@types/node": "^17.0.40", | ||
"brotli-wasm": "^1.2.0", | ||
"buffer": "^6.0.3" | ||
"brotli-wasm": "1.2.0" | ||
}, | ||
@@ -43,0 +42,0 @@ "devDependencies": { |
128
README.md
# brotli-compress | ||
This package is a re-packaging of `brotli-wasm` that works consistently | ||
in Node.js and Browser environments. The WASM module has been bundled in | ||
and inlined as base64 encoded binary data; therfore it doesn't need to be | ||
loaded from a separate file. This solves the following issue with `wasm-pack`: | ||
This package packages `brotli-wasm`, minifies and inlines it, so that it works consistently | ||
in Node.js and Browser environments. This solves [several issues](https://github.com/rustwasm/wasm-pack/issues/1106) of using `brotli-wasm` directly. | ||
- https://github.com/rustwasm/wasm-pack/issues/1106 | ||
Furthermore, this package comes with two module variants: CommonJS and ESM. | ||
On top of this, this library comes with a copy of the original Brotli `decompress` | ||
implementation by Google, with an optimited API to be 1:1 compatible with | ||
the WASM variant and with TypeScript typing support. | ||
Furthermore, the build script used in this package bundles in different | ||
output variants: CommonJS and ESM. On top of this, the library uses the | ||
`buffer` package internally to polyfill the missing implementation in | ||
Browser environments. | ||
All in all, this package is the Brotli "fire and forget" solution that should | ||
work in all JavaScript environments, with all bundlers and ecosystems, including | ||
Vite, Rollup, Webpack, Gatsby and Next.js projects as well as Node.js. | ||
This makes the package easier to use with other bundlers like Vite, | ||
Rollup, Webpack, etc. and leads to a seamless integration e.g. into | ||
Gatsby and Next.js projects. | ||
## Setup | ||
@@ -31,3 +27,3 @@ | ||
## Usage | ||
## Usage of the WASM variant | ||
@@ -37,32 +33,102 @@ The usage in a Node.js or Browser environment is trivial: | ||
```ts | ||
// import size (uncompressed, but minified) / WASM version / max performance: 1.8M | ||
import { compress, decompress } from 'brotli-compress' | ||
const oneBlockInput = 'Hello🤖!' | ||
// it takes a Int8Array and returns a Int8Array | ||
const compressed = await compress(oneBlockInput) | ||
// it takes a Int8Array and returns a Int8Array | ||
const decompressed = await decompress(compressed) | ||
``` | ||
Please note that the WASM version comes with a whopping size of (minified) | ||
1.8MiB. This is, because the binary is base64 encoded and inlined. | ||
If you prefer maximum performance and memory efficiency over small bundle size, | ||
choose the WASM variant. Also, if you need compression, use the WASM version. | ||
## Usage of the pure JS variant | ||
If you need a small bundle size, can effort the slowdown and | ||
only need decompression, use the hard-written JavaScript decompressor: | ||
```ts | ||
// import size (uncompressed, but minified) / JS version / only decompress / slower: 152K | ||
import { decompress } from 'brotli-compress/js' | ||
// please also note that the pure JS variant is synchronous | ||
// for large inputs, you could optimize the execution by moving | ||
// this call into a Worker | ||
// it takes a Uint8Array and returns a Uint8Array | ||
const decompressed = decompress(compressed) | ||
``` | ||
## Encoding to Uint8Array and decoding from Uint8Array | ||
For Node.js, you'd be well advised to use the built-in `Buffer` package: | ||
```ts | ||
import { Buffer } from 'buffer' | ||
const testInput = 'Hello🤖!' | ||
const testInputUint8 = Buffer.from(testInput) | ||
const compressed = await compress(testInputUint8) | ||
const decompressed = await decompress(compressed) | ||
const decompressedString = Buffer.from(decompressed).toString() | ||
``` | ||
For use in browser/frontend, you can either use `TextEncoder` and `TextDecoder` | ||
or use a polyfill like the [buffer](https://www.npmjs.com/package/buffer) library. | ||
```ts | ||
new TextEncoder().encode(testInput) // returns a Uint8Array | ||
new TextDecoder().decode(compressed) // returns a string from the compressed Uint8Array | ||
``` | ||
## Options | ||
Compress comes with an options object as a second parameter: | ||
The `compress` method comes with a second `options` parameter. | ||
### Quality level | ||
The most common setting is `quality` with a scale from 0 to 11. | ||
By default, the quality is set to best quality (11). | ||
```ts | ||
const compressed = await compress('foobar', { quality: 12 }) | ||
const compressed = await compress(Buffer.from('foobar'), { quality: 9 }) | ||
``` | ||
The only option known to me at the moment is `quality`. | ||
A lower quality value makes the output bigger but improves compression time. | ||
In 99.9% of the cases, you don't want to change this value. | ||
## Limitations | ||
### Custom dictionary | ||
I'm planning to add Stream compression as well and add all | ||
the unit tests of the original package. | ||
The relevant options here is `customDictionary`. You can set this to an Uint8Array string | ||
of tokens which should be part of the `a priori` known dictionary. This can be useful | ||
if you have power over both, the sender and the receiver part and if you know exactly | ||
which tokens will be used alot in the input. For example, if you know that you'll | ||
be compressing text, encoded as UTF16/UCS-2 and you know that the content is TypeScript code, | ||
you could include the keywords of the TypeScript language in the custom dictionary. | ||
## Roadmap | ||
Please mind, that you need to set the same value for decoding as well. | ||
It might be wise to remove the `buffer` library and replace | ||
it with TextEncoder and TextDecoder in browser environments. | ||
```ts | ||
// with this configuration, "let" must not be encoded in the dictionary and carried as part of the | ||
// payload. The binary tree (huffman coding tree) | ||
const customDictionary = Buffer.from('let') | ||
const compressed = await compress('let foo = 123; let bar = "foo";', { customDictionary }) | ||
const decompressed = await decompress(compressed, { customDictionary }) | ||
``` | ||
## Limitations | ||
There is no streaming compression/decompression yet. It can be simply done by exposing the API from the WASM implementation. | ||
If you need that, pls. ping via Issue. | ||
## Build | ||
yarn build | ||
yarn build | ||
@@ -72,1 +138,15 @@ ## Test | ||
yarn test | ||
## Licensing | ||
Most of the code of this library is licensed by Apache-2.0. | ||
The original `decompress` implementation is licensed by Google under MIT license (src/js.ts). | ||
## Contibutors | ||
Package and build configuration plus cross-library implementation, documentation and | ||
unit testing, as well as updating the WASM/JS binding has been done by Aron Homberg. | ||
`brotli-wasm` that ships with this package inline as been implemented by [Tim Perry](https://github.com/httptoolkit/brotli-wasm) and contributors. | ||
Direct binding WASM/JS and the respective code extraction idea has been implemented by [stefnotch](https://github.com/stefnotch/url-catpressor/blob/main/src/useCompression.ts) |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
4065104
4.56%2
-33.33%10
42.86%150
114.29%0
-100%15898
-15.44%+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
Updated