Skip to content

Commit 5b76597

Browse files
committed
add wasm compression at build
1 parent 6e0ee78 commit 5b76597

4 files changed

Lines changed: 64 additions & 20 deletions

File tree

package-lock.json

Lines changed: 20 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"type": "module",
66
"engines": {
7-
"node": ">=24.18.0 <25"
7+
"node": ">=24.18.0 <27"
88
},
99
"scripts": {
1010
"dev": "vite",
@@ -36,6 +36,7 @@
3636
"prettier": "3.9.1",
3737
"typescript": "~6.0.3",
3838
"vite": "^8.1.0",
39+
"vite-plugin-compression2": "^2.5.3",
3940
"vite-plugin-pwa": "^1.3.0",
4041
"vue-tsc": "^3.3.5"
4142
}

src/wasm/worker.ts

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ interface RpcRequest {
3838
args: unknown[];
3939
}
4040

41-
const MB = 1_048_576;
41+
const MB = 1_000_000;
4242
let wasmReadyPromise: Promise<void> | null = null;
4343

4444
// ─────────────────────────────────────────────────────────────────────────────
@@ -58,42 +58,47 @@ function progress(percentage: number, text_id: string, other: string = '') {
5858

5959
async function fetchWasm(url: string): Promise<ArrayBuffer> {
6060
const response = await fetch(url);
61-
if (!response.ok || !response.body) {
62-
throw new Error(`WASM fetch failed: HTTP ${response.status} or missing body`);
61+
if (!response.ok) {
62+
throw new Error(`WASM fetch failed: HTTP ${response.status}`);
63+
}
64+
if (!response.body) {
65+
throw new Error('WASM fetch failed: missing body');
66+
}
67+
68+
const total = Number(response.headers.get('Content-Length'));
69+
if (!total) {
70+
throw new Error('WASM fetch failed: missing Content-Length');
6371
}
6472

65-
const contentLength = response.headers.get('Content-Length');
66-
const encoding = response.headers.get('Content-Encoding');
67-
const total = contentLength ? parseInt(contentLength, 10) : 1;
6873
const reader = response.body.getReader();
6974
const chunks: Uint8Array[] = [];
75+
7076
let received = 0;
7177

7278
while (true) {
7379
const { done, value } = await reader.read();
74-
if (done) break;
80+
if (done) {
81+
break;
82+
}
7583

7684
chunks.push(value);
7785
received += value.byteLength;
78-
const encodedRecieved = received / (encoding == 'gzip' ? 4 : 1); // account for ~4x compression with Gzip
7986

80-
const pct = total ? 5 + Math.round((encodedRecieved / total) * 85) : 50;
81-
const sizeMsg = total
82-
? `${(encodedRecieved / MB).toFixed(1)} / ${(total / MB).toFixed(1)} MB`
83-
: `${(encodedRecieved / MB).toFixed(1)} MB`;
87+
const pct = 5 + Math.round((received / total) * 85);
88+
const sizeMsg = `${(received / MB).toFixed(1)} / ${(total / MB).toFixed(1)} MB`;
8489

85-
progress(Math.min(pct, 90), `fetchingWasm`, sizeMsg);
90+
progress(Math.min(pct, 90), 'fetchingWasm', sizeMsg);
8691
}
8792

88-
// Merge chunks
89-
const merged = new Uint8Array(received);
93+
const wasm = new Uint8Array(received);
9094
let offset = 0;
95+
9196
for (const chunk of chunks) {
92-
merged.set(chunk, offset);
97+
wasm.set(chunk, offset);
9398
offset += chunk.byteLength;
9499
}
95100

96-
return merged.buffer;
101+
return wasm.buffer;
97102
}
98103

99104
// ─────────────────────────────────────────────────────────────────────────────

vite.config.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { fileURLToPath, URL } from 'node:url';
22

33
import { defineConfig } from 'vite';
44
import vue from '@vitejs/plugin-vue';
5+
import { compression, defineAlgorithm } from 'vite-plugin-compression2';
6+
import { constants } from 'node:zlib';
57
import { VitePWA } from 'vite-plugin-pwa';
68

79
const base = process.env.GITHUB_PAGES == 'true' ? '/web-client/' : '/';
@@ -11,6 +13,23 @@ export default defineConfig({
1113
base,
1214
plugins: [
1315
vue(),
16+
// compress wasm files to brotli, zstd and gzip
17+
compression({
18+
include: /\.wasm$/,
19+
algorithms: [
20+
defineAlgorithm('gzip', { level: 9 }),
21+
defineAlgorithm('zstandard', {
22+
params: {
23+
[constants.ZSTD_c_compressionLevel]: 19,
24+
},
25+
}),
26+
defineAlgorithm('brotliCompress', {
27+
params: {
28+
[require('zlib').constants.BROTLI_PARAM_QUALITY]: 11,
29+
},
30+
}),
31+
],
32+
}),
1433
VitePWA({
1534
registerType: 'autoUpdate',
1635
manifest: {
@@ -41,7 +60,7 @@ export default defineConfig({
4160
},
4261

4362
workbox: {
44-
globPatterns: ['**/*.{js,css,html,ico,png,svg,webp,woff2,wasm}'],
63+
globPatterns: ['**/*.{js,css,html,ico,png,svg,webp,woff2,wasm,zst,br,gz}'],
4564
maximumFileSizeToCacheInBytes: 25 * 1024 * 1024, // 25MiB (core.wasm is a big boy)
4665
cleanupOutdatedCaches: true,
4766
navigateFallback: `${base}index.html`,

0 commit comments

Comments
 (0)