Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitattributes
Comment thread
allozaur marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Treat the generated single-file WebUI build as binary for diff purposes.
# Git's pack-file delta compression still works (byte-level), but this prevents
# git diff from printing the entire minified file on every change.
tools/server/public/index.html -diff
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@
# Server Web UI temporary files
/tools/server/webui/node_modules
/tools/server/webui/dist
# we no longer use gz for index.html
/tools/server/public/index.html.gz

# Python

Expand Down
2 changes: 1 addition & 1 deletion tools/server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ option(LLAMA_BUILD_WEBUI "Build the embedded Web UI" ON)

if (LLAMA_BUILD_WEBUI)
set(PUBLIC_ASSETS
index.html.gz
index.html
loading.html
)

Expand Down
2 changes: 1 addition & 1 deletion tools/server/README-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,6 @@ npm run test
npm run build
```

After `public/index.html.gz` has been generated, rebuild `llama-server` as described in the [build](#build) section to include the updated UI.
After `public/index.html` has been generated, rebuild `llama-server` as described in the [build](#build) section to include the updated UI.

**Note:** The Vite dev server automatically proxies API requests to `http://localhost:8080`. Make sure `llama-server` is running on that port during development.
508 changes: 508 additions & 0 deletions tools/server/public/index.html

Large diffs are not rendered by default.

Binary file removed tools/server/public/index.html.gz
Binary file not shown.
17 changes: 6 additions & 11 deletions tools/server/server-http.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#ifdef LLAMA_BUILD_WEBUI
// auto generated files (see README.md for details)
#include "index.html.gz.hpp"
#include "index.html.hpp"
#include "loading.html.hpp"
#endif

Expand Down Expand Up @@ -262,16 +262,11 @@ bool server_http_context::init(const common_params & params) {
} else {
#ifdef LLAMA_BUILD_WEBUI
// using embedded static index.html
srv->Get(params.api_prefix + "/", [](const httplib::Request & req, httplib::Response & res) {
if (req.get_header_value("Accept-Encoding").find("gzip") == std::string::npos) {
res.set_content("Error: gzip is not supported by this browser", "text/plain");
} else {
res.set_header("Content-Encoding", "gzip");
// COEP and COOP headers, required by pyodide (python interpreter)
res.set_header("Cross-Origin-Embedder-Policy", "require-corp");
res.set_header("Cross-Origin-Opener-Policy", "same-origin");
res.set_content(reinterpret_cast<const char*>(index_html_gz), index_html_gz_len, "text/html; charset=utf-8");
}
srv->Get(params.api_prefix + "/", [](const httplib::Request & /*req*/, httplib::Response & res) {
// COEP and COOP headers, required by pyodide (python interpreter)
res.set_header("Cross-Origin-Embedder-Policy", "require-corp");
res.set_header("Cross-Origin-Opener-Policy", "same-origin");
res.set_content(reinterpret_cast<const char*>(index_html), index_html_len, "text/html; charset=utf-8");
return false;
});
#endif
Expand Down
1 change: 0 additions & 1 deletion tools/server/webui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-storybook": "^10.2.4",
"eslint-plugin-svelte": "^3.0.0",
"fflate": "^0.8.2",
"globals": "^16.0.0",
"http-server": "^14.1.1",
"mdast": "^3.0.0",
Expand Down
6 changes: 3 additions & 3 deletions tools/server/webui/scripts/install-git-hooks.sh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ngxson this PR is a good opportunity to move the build of index.html to CI in order to avoid the merge conflicts with static build output for most of the webui PRs that don't have recent master as base (or don't have it merged in).

Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ if [ -n "$WEBUI_CHANGES" ]; then
fi

# Check if build output exists and is newer than source files
BUILD_FILE="../public/index.html.gz"
BUILD_FILE="../public/index.html"
NEEDS_BUILD=false

if [ ! -f "$BUILD_FILE" ]; then
Expand Down Expand Up @@ -127,9 +127,9 @@ if [ -n "$WEBUI_CHANGES" ]; then
cd ../../..

# Check if build output was created/updated
if [ -f "tools/server/public/index.html.gz" ]; then
if [ -f "tools/server/public/index.html" ]; then
# Add the build output and commit it
git add tools/server/public/index.html.gz
git add tools/server/public/index.html
if ! git diff --cached --quiet; then
echo "Committing updated build output..."
git commit -m "chore: update webui build output"
Expand Down
2 changes: 1 addition & 1 deletion tools/server/webui/scripts/post-build.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
rm -rf ../public/_app;
rm ../public/favicon.svg;
rm ../public/index.html;
rm -f ../public/index.html.gz; # deprecated, but may still be generated by older versions of the build process
27 changes: 4 additions & 23 deletions tools/server/webui/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import tailwindcss from '@tailwindcss/vite';
import { sveltekit } from '@sveltejs/kit/vite';
import * as fflate from 'fflate';
import { readFileSync, writeFileSync, existsSync } from 'fs';
import { dirname, resolve } from 'path';
import { fileURLToPath } from 'url';
Expand All @@ -20,15 +19,13 @@ const GUIDE_FOR_FRONTEND = `
-->
`.trim();

const MAX_BUNDLE_SIZE = 2 * 1024 * 1024;

/**
* the maximum size of an embedded asset in bytes,
* e.g. maximum size of embedded font (see node_modules/katex/dist/fonts/*.woff2)
*/
const MAX_ASSET_SIZE = 32000;

/** public/index.html.gz minified flag */
/** public/index.html minified flag */
const ENABLE_JS_MINIFICATION = true;

function llamaCppBuildPlugin() {
Expand All @@ -40,7 +37,6 @@ function llamaCppBuildPlugin() {
setTimeout(() => {
try {
const indexPath = resolve('../public/index.html');
const gzipPath = resolve('../public/index.html.gz');

if (!existsSync(indexPath)) {
return;
Expand All @@ -62,25 +58,10 @@ function llamaCppBuildPlugin() {
content = content.replace(/\r/g, '');
content = GUIDE_FOR_FRONTEND + '\n' + content;

const compressed = fflate.gzipSync(Buffer.from(content, 'utf-8'), { level: 9 });

compressed[0x4] = 0;
compressed[0x5] = 0;
compressed[0x6] = 0;
compressed[0x7] = 0;
compressed[0x9] = 0;

if (compressed.byteLength > MAX_BUNDLE_SIZE) {
throw new Error(
`Bundle size is too large (${Math.ceil(compressed.byteLength / 1024)} KB).\n` +
`Please reduce the size of the frontend or increase MAX_BUNDLE_SIZE in vite.config.ts.\n`
);
}

writeFileSync(gzipPath, compressed);
console.log('✓ Created index.html.gz');
writeFileSync(indexPath, content, 'utf-8');
console.log('✓ Updated index.html');
} catch (error) {
console.error('Failed to create gzip file:', error);
console.error('Failed to update index.html:', error);
}
}, 100);
}
Expand Down
Loading