Skip to content

Commit b74e1b6

Browse files
committed
server: Compress index.html with brotli
brotli is a widely used content encoding for web pages. Specifically it shaves off ~400kb from index.html. Before: 1.519.342 tools/server/public/index.html.br After: 1.912.690 tools/server/public/index.html.gz Delta: -393.348 brotli is also deterministic so we don't need to manually zero-out fields in the output.
1 parent 6a2bc8b commit b74e1b6

File tree

8 files changed

+18
-31
lines changed

8 files changed

+18
-31
lines changed

tools/server/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ set(TARGET_SRCS
1515
httplib.h
1616
)
1717
set(PUBLIC_ASSETS
18-
index.html.gz
18+
index.html.br
1919
loading.html
2020
)
2121

tools/server/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,11 +270,11 @@ npm i
270270
# to run the dev server
271271
npm run dev
272272
273-
# to build the public/index.html.gz
273+
# to build the public/index.html.br
274274
npm run build
275275
```
276-
After `public/index.html.gz` has been generated we need to generate the c++
277-
headers (like build/tools/server/index.html.gz.hpp) that will be included
276+
After `public/index.html.br` has been generated we need to generate the c++
277+
headers (like build/tools/server/index.html.br.hpp) that will be included
278278
by server.cpp. This is done by building `llama-server` as described in the
279279
[build](#build) section above.
280280

tools/server/public/index.html.br

1.45 MB
Binary file not shown.

tools/server/public/index.html.gz

-1.82 MB
Binary file not shown.

tools/server/server.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#define MIMETYPE_JSON "application/json; charset=utf-8"
1717

1818
// auto generated files (see README.md for details)
19-
#include "index.html.gz.hpp"
19+
#include "index.html.br.hpp"
2020
#include "loading.html.hpp"
2121

2222
#include <atomic>
@@ -4701,14 +4701,14 @@ int main(int argc, char ** argv) {
47014701
} else {
47024702
// using embedded static index.html
47034703
svr->Get("/", [](const httplib::Request & req, httplib::Response & res) {
4704-
if (req.get_header_value("Accept-Encoding").find("gzip") == std::string::npos) {
4705-
res.set_content("Error: gzip is not supported by this browser", "text/plain");
4704+
if (req.get_header_value("Accept-Encoding").find("br") == std::string::npos) {
4705+
res.set_content("Error: brotli is not supported by this browser", "text/plain");
47064706
} else {
4707-
res.set_header("Content-Encoding", "gzip");
4707+
res.set_header("Content-Encoding", "br");
47084708
// COEP and COOP headers, required by pyodide (python interpreter)
47094709
res.set_header("Cross-Origin-Embedder-Policy", "require-corp");
47104710
res.set_header("Cross-Origin-Opener-Policy", "same-origin");
4711-
res.set_content(reinterpret_cast<const char*>(index_html_gz), index_html_gz_len, "text/html; charset=utf-8");
4711+
res.set_content(reinterpret_cast<const char*>(index_html_br), index_html_br_len, "text/html; charset=utf-8");
47124712
}
47134713
return false;
47144714
});

tools/server/webui/package-lock.json

Lines changed: 0 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tools/server/webui/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@
4848
"eslint": "^9.17.0",
4949
"eslint-plugin-react-hooks": "^5.0.0",
5050
"eslint-plugin-react-refresh": "^0.4.16",
51-
"fflate": "^0.8.2",
5251
"globals": "^15.14.0",
5352
"prettier": "^3.4.2",
5453
"sass-embedded": "^1.83.4",

tools/server/webui/vite.config.ts

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import react from '@vitejs/plugin-react';
33
import { viteSingleFile } from 'vite-plugin-singlefile';
44
import path from 'node:path';
55
import fs from 'node:fs';
6-
import * as fflate from 'fflate';
6+
import zlib from 'node:zlib';
77

88
/* eslint-disable */
99

@@ -36,19 +36,15 @@ const BUILD_PLUGINS = [
3636
let content =
3737
GUIDE_FOR_FRONTEND + '\n' + fs.readFileSync(outputIndexHtml, 'utf-8');
3838
content = content.replace(/\r/g, ''); // remove windows-style line endings
39-
const compressed = fflate.gzipSync(Buffer.from(content, 'utf-8'), {
40-
level: 9,
39+
const compressed = zlib.brotliCompressSync(Buffer.from(content), {
40+
params: {
41+
[zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,
42+
[zlib.constants.BROTLI_PARAM_QUALITY]:
43+
zlib.constants.BROTLI_MAX_QUALITY,
44+
[zlib.constants.BROTLI_PARAM_SIZE_HINT]: content.length,
45+
},
4146
});
4247

43-
// because gzip header contains machine-specific info, we must remove these data from the header
44-
// timestamp
45-
compressed[0x4] = 0;
46-
compressed[0x5] = 0;
47-
compressed[0x6] = 0;
48-
compressed[0x7] = 0;
49-
// OS
50-
compressed[0x9] = 0;
51-
5248
if (compressed.byteLength > MAX_BUNDLE_SIZE) {
5349
throw new Error(
5450
`Bundle size is too large (${Math.ceil(compressed.byteLength / 1024)} KB).\n` +
@@ -58,7 +54,7 @@ const BUILD_PLUGINS = [
5854

5955
const targetOutputFile = path.join(
6056
config.build.outDir,
61-
'../../public/index.html.gz'
57+
'../../public/index.html.br'
6258
);
6359
fs.writeFileSync(targetOutputFile, compressed);
6460
},

0 commit comments

Comments
 (0)