Skip to content

Commit 1b48dc5

Browse files
authored
Merge pull request #13 from jonluca/feat/only-changes
Create web version of build for vite & rollup
2 parents fcd17ae + 675cbc4 commit 1b48dc5

File tree

11 files changed

+212
-85
lines changed

11 files changed

+212
-85
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,5 @@ dist
106106
# Rust:
107107
/target
108108
/pkg
109-
/pkg.*/
109+
/pkg.*/
110+
.idea/

README.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,17 @@ This is battle-tested, in production use in both node & browsers as part of [HTT
1616
npm install brotli-wasm
1717
```
1818

19-
You should be able to import this directly into Node, as normal, or into a browser using any bundler that supports ES modules & webassembly (e.g. Webpack v4 or v5).
19+
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).
2020

21-
The browser build supports both sync (v4 or v5 syncWebAssembly mode) and async (v5 asyncWebAssembly) builds. When imported in a browser build the module always exports a _promise_, not a fixed value, as this is a requirement for synchronous builds, and you will need to `await` this after import.
21+
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).
2222

23-
In both builds, the module exposes two methods:
23+
In all builds (after waiting for the exported promise in browsers) the module exposes two core methods:
2424

2525
* `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.
2626
* `decompress(Buffer)` - decompresses a buffer using Brotli, returning the original raw data.
2727

28+
### Usage
29+
2830
In node.js:
2931

3032
```javascript
@@ -39,7 +41,7 @@ console.log(Buffer.from(decompressedData).toString('utf8')); // Prints 'some inp
3941
In browsers:
4042

4143
```javascript
42-
import * as brotliPromise from 'brotli-wasm';
44+
import brotliPromise from 'brotli-wasm'; // Import the default export
4345

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

@@ -49,9 +51,9 @@ const decompressedData = brotli.decompress(compressedData);
4951
console.log(Buffer.from(decompressedData).toString('utf8')); // Prints 'some input'
5052
```
5153

52-
You'll need a [browser Buffer polyfill](https://www.npmjs.com/package/browserify-zlib) for the above, or you can do the same using TextEncoder/Decoder instead if you prefer.
54+
The package itself has no runtime dependencies, but you will need a [browser Buffer polyfill](https://www.npmjs.com/package/browserify-zlib) for the above example code, or you can do the same using TextEncoder/Decoder instead if you prefer.
5355

54-
If you want to support node & browsers with the same code, you can use the latter `await` form here everywhere (since awaiting the fixed value in node just returns the value as-is).
56+
If you want to support node & browsers with the same code, you can use the `await` form with the default export everywhere.
5557

5658
## Alternatives
5759

build.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,10 @@ shell.rm('pkg.bundler/{LICENSE,package.json,README.md,.gitignore}');
1919
shell.rm('-rf', 'pkg');
2020
shell.exec('wasm-pack build --target nodejs');
2121
shell.mv('pkg', 'pkg.node');
22-
shell.rm('pkg.node/{LICENSE,package.json,README.md,.gitignore}');
22+
shell.rm('pkg.node/{LICENSE,package.json,README.md,.gitignore}');
23+
24+
// Create the web output
25+
shell.rm('-rf', 'pkg');
26+
shell.exec('wasm-pack build --target web');
27+
shell.mv('pkg', 'pkg.web');
28+
shell.rm('pkg.web/{LICENSE,package.json,README.md,.gitignore}');

index.browser.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,10 @@
33
// allow synchronous import of WebAssembly from an entrypoint.
44
module.exports = import("./pkg.bundler/brotli_wasm.js");
55

6-
// We don't want to do this for _all_ usage, because dynamic import isn't
7-
// supported in older node versions.
6+
// In addition, we provide a default export with the same value, for compatibility
7+
// with the pure ESM web bundle:
8+
module.exports.default = module.exports;
9+
10+
// Without this, ts-loader gets annoyed by imports for the pure type. Clear ts-loader bug,
11+
// but this is a quick & easy fix on our end:
12+
module.exports.BrotliWasmType = undefined;

index.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import * as BrotliWasm from './pkg.node/brotli_wasm';
2+
3+
// Re-export the core API - although this will only work OOTB for node usage.
4+
export * from './pkg.node/brotli_wasm';
5+
6+
declare const promisedValue: Promise<typeof BrotliWasm>;
7+
export default promisedValue;
8+
9+
export type BrotliWasmType = typeof BrotliWasm;

index.node.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// In Node, everything is conveniently available synchronously.
2+
const nodePkg = require('./pkg.node/brotli_wasm');
3+
module.exports = nodePkg;
4+
5+
// In addition though, we provide a default export, to match the pure ESM web bundle:
6+
module.exports.default = Promise.resolve(nodePkg);

index.web.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// In pure ESM web bundles, you must call init() and wait for the promised result before you can
2+
// call any module methods. To make that as easy as possible, this module directly exposes the
3+
// init() promise result, and returns the methods at the end of the promise.
4+
import init, * as brotliWasm from "./pkg.web/brotli_wasm";
5+
export default init().then(() => brotliWasm);

karma-esm.conf.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Karma-vite breaks Karma in Node <14, and browser tests don't depend on Node versions, so
2+
// we just skip the tests in those environments.
3+
const nodeMajorVersion = parseInt(process.versions.node.split('.'));
4+
if (nodeMajorVersion <= 14) {
5+
console.log('Skipping browser tests in old node version');
6+
process.exit(0);
7+
}
8+
9+
module.exports = function(config) {
10+
config.set({
11+
frameworks: ['mocha', 'chai', 'vite'],
12+
files: [
13+
{
14+
pattern: 'test/**/*.spec.ts',
15+
type: 'module',
16+
watched: false,
17+
served: false,
18+
}
19+
],
20+
mime: {
21+
'text/x-typescript': ['ts']
22+
},
23+
reporters: ['spec'],
24+
port: 9876,
25+
logLevel: config.LOG_INFO,
26+
27+
browsers: ['ChromeHeadless'],
28+
29+
autoWatch: false,
30+
singleRun: true,
31+
concurrency: Infinity
32+
});
33+
};

karma.conf.js renamed to karma-webpack.conf.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1+
// Karma-vite breaks Karma in Node <14, and browser tests don't depend on Node versions, so
2+
// we just skip the tests in those environments.
3+
const nodeMajorVersion = parseInt(process.versions.node.split('.'));
4+
if (nodeMajorVersion <= 14) {
5+
console.log('Skipping browser tests in old node version');
6+
process.exit(0);
7+
}
8+
19
const tmp = require('tmp');
210
tmp.setGracefulCleanup();
311

4-
const webpack = require('webpack');
5-
612
const outputDir = tmp.dirSync({ unsafeCleanup: true }).name;
713

814
module.exports = function(config) {
@@ -38,17 +44,12 @@ module.exports = function(config) {
3844
resolve: {
3945
extensions: ['.ts', '.js'],
4046
fallback: {
41-
buffer: require.resolve('buffer/')
47+
crypto: false
4248
}
4349
},
4450
experiments: {
4551
asyncWebAssembly: true
4652
},
47-
plugins: [
48-
new webpack.ProvidePlugin({
49-
Buffer: ['buffer', 'Buffer'],
50-
})
51-
],
5253
output: {
5354
path: outputDir
5455
}

package.json

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,36 @@
22
"name": "brotli-wasm",
33
"version": "1.2.0",
44
"description": "A reliable compressor and decompressor for Brotli, supporting node & browsers via wasm",
5-
"main": "./pkg.node/brotli_wasm.js",
6-
"types": "./pkg.node/brotli_wasm.d.ts",
5+
"types": "./index.d.ts",
6+
"main": "./index.node.js",
77
"browser": "./index.browser.js",
8+
"exports": {
9+
".": {
10+
"import": "./index.web.js",
11+
"browser": "./index.browser.js",
12+
"require": "./index.node.js",
13+
"default": "./index.web.js"
14+
}
15+
},
816
"sideEffects": false,
917
"files": [
1018
"pkg.node",
1119
"pkg.bundler",
12-
"index.browser.js"
20+
"pkg.web",
21+
"index.node.js",
22+
"index.browser.js",
23+
"index.web.js",
24+
"index.d.ts"
1325
],
1426
"scripts": {
1527
"build": "node ./build.js",
1628
"pretest": "npm run build",
17-
"test": "npm run test:node && npm run test:browser",
18-
"test:node": "TS_NODE_FILES=true mocha -r ts-node/register 'test/**/*.spec.ts'",
19-
"test:browser": "karma start",
20-
"test:browser:debug": "npm run test:browser -- --single-run=false --browsers Chrome"
29+
"test": "npm run test:node && npm run test:esm && npm run test:webpack",
30+
"test:node": "ts-mocha -p test/tsconfig.json 'test/**/*.spec.ts'",
31+
"test:webpack": "karma start ./karma-webpack.conf.js",
32+
"test:esm": "karma start ./karma-esm.conf.js",
33+
"test:webpack:debug": "npm run test:webpack -- --single-run=false --browsers Chrome",
34+
"test:esm:debug": "npm run test:esm -- --single-run=false --browsers Chrome"
2135
},
2236
"repository": {
2337
"type": "git",
@@ -36,9 +50,15 @@
3650
},
3751
"homepage": "https://github.com/httptoolkit/brotli-wasm#readme",
3852
"devDependencies": {
53+
"@peculiar/webcrypto": "^1.4.0",
54+
"@types/atob": "^2.1.2",
55+
"@types/btoa": "^1.2.3",
3956
"@types/chai": "^4.2.18",
4057
"@types/mocha": "^8.2.2",
4158
"@types/node": "^15.6.0",
59+
"@types/text-encoding": "0.0.36",
60+
"atob": "^2.1.2",
61+
"btoa": "^1.2.1",
4262
"buffer": "^6.0.3",
4363
"chai": "^4.3.4",
4464
"karma": "^6.3.2",
@@ -48,13 +68,16 @@
4868
"karma-sourcemap-loader": "^0.3.8",
4969
"karma-spec-reporter": "0.0.32",
5070
"karma-typescript": "^5.5.1",
71+
"karma-vite": "^1.0.1",
5172
"karma-webpack": "^5.0.0",
5273
"mocha": "^8.4.0",
5374
"shelljs": "^0.8.4",
75+
"text-encoding": "^0.7.0",
5476
"ts-loader": "^9.2.1",
77+
"ts-mocha": "^10.0.0",
5578
"ts-node": "^9.1.1",
5679
"typescript": "^4.2.4",
57-
"wasm-pack": "^0.9.1",
80+
"wasm-pack": "^0.10.3",
5881
"webpack": "^5.37.1"
5982
}
6083
}

0 commit comments

Comments
 (0)