Skip to content

Commit 3642578

Browse files
committed
Precompress production assets
1 parent b62b424 commit 3642578

3 files changed

Lines changed: 79 additions & 2 deletions

File tree

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,11 @@ The `dev` command automatically copies the multithreaded WASM modules from `@lad
2121
pnpm build
2222
```
2323

24-
This builds both the WASM modules and the production bundle.
24+
This builds both the WASM modules and the production bundle, then writes
25+
precompressed `.gz` and `.br` versions of text/WASM assets in `dist/`.
26+
27+
The web server or CDN must serve those files with `Content-Encoding: gzip` or
28+
`Content-Encoding: br` for browsers to use them. GitHub Pages does not expose
29+
custom response-header configuration from this repository; use a CDN or static
30+
host that supports precompressed assets if you need to control compression
31+
explicitly.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
"predev": "pnpm run build:wasm",
88
"build:wasm": "cp node_modules/@ladybugdb/wasm-core/multithreaded/index.js lib/index.js && cp node_modules/@ladybugdb/wasm-core/multithreaded/lbug_wasm_worker.js lib/lbug_wasm_worker.js && cp node_modules/@ladybugdb/wasm-core/multithreaded/sync/index.js sync/index.js",
99
"dev": "vite",
10-
"build": "pnpm run build:wasm && vite build && pnpm run copy:lib",
10+
"build": "pnpm run build:wasm && vite build && pnpm run copy:lib && pnpm run compress:dist",
1111
"copy:lib": "node -e \"const {copyFileSync,mkdirSync,existsSync}=require('fs');const d='dist/lib';if(!existsSync(d))mkdirSync(d,{recursive:true});['index.js','lbug_wasm_worker.js'].forEach(f=>copyFileSync('lib/'+f,d+'/'+f));const s='dist/sync';if(!existsSync(s))mkdirSync(s,{recursive:true});copyFileSync('sync/index.js',s+'/index.js')\"",
12+
"compress:dist": "node scripts/compress-dist.mjs",
1213
"preview": "vite preview"
1314
},
1415
"dependencies": {

scripts/compress-dist.mjs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { createReadStream, createWriteStream, statSync } from 'node:fs';
2+
import { readdir } from 'node:fs/promises';
3+
import { extname, join } from 'node:path';
4+
import { pipeline } from 'node:stream/promises';
5+
import { createBrotliCompress, createGzip, constants } from 'node:zlib';
6+
7+
const DIST_DIR = 'dist';
8+
const MIN_BYTES = 1024;
9+
const COMPRESSIBLE_EXTENSIONS = new Set([
10+
'.css',
11+
'.html',
12+
'.js',
13+
'.json',
14+
'.mjs',
15+
'.svg',
16+
'.txt',
17+
'.wasm',
18+
'.xml',
19+
]);
20+
21+
async function* walk(dir) {
22+
for (const entry of await readdir(dir, { withFileTypes: true })) {
23+
const path = join(dir, entry.name);
24+
if (entry.isDirectory()) {
25+
yield* walk(path);
26+
} else if (entry.isFile()) {
27+
yield path;
28+
}
29+
}
30+
}
31+
32+
async function compressFile(path) {
33+
await pipeline(
34+
createReadStream(path),
35+
createGzip({ level: 9 }),
36+
createWriteStream(`${path}.gz`),
37+
);
38+
39+
await pipeline(
40+
createReadStream(path),
41+
createBrotliCompress({
42+
params: {
43+
[constants.BROTLI_PARAM_QUALITY]: 11,
44+
},
45+
}),
46+
createWriteStream(`${path}.br`),
47+
);
48+
}
49+
50+
let compressedCount = 0;
51+
52+
for await (const path of walk(DIST_DIR)) {
53+
if (path.endsWith('.gz') || path.endsWith('.br')) {
54+
continue;
55+
}
56+
57+
if (!COMPRESSIBLE_EXTENSIONS.has(extname(path))) {
58+
continue;
59+
}
60+
61+
if (statSync(path).size < MIN_BYTES) {
62+
continue;
63+
}
64+
65+
await compressFile(path);
66+
compressedCount += 1;
67+
}
68+
69+
console.log(`Compressed ${compressedCount} dist asset${compressedCount === 1 ? '' : 's'}.`);

0 commit comments

Comments
 (0)