diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..06c85ad56e --- /dev/null +++ b/.gitattributes @@ -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 diff --git a/.gitignore b/.gitignore index 73954e8f5d..7997029849 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/tools/server/CMakeLists.txt b/tools/server/CMakeLists.txt index fc4cb5dcc8..6520ca4902 100644 --- a/tools/server/CMakeLists.txt +++ b/tools/server/CMakeLists.txt @@ -38,7 +38,7 @@ set(TARGET_SRCS server-models.h ) set(PUBLIC_ASSETS - index.html.gz + index.html loading.html ) diff --git a/tools/server/README-dev.md b/tools/server/README-dev.md index 1dd00b72e4..a9c1e7385f 100644 --- a/tools/server/README-dev.md +++ b/tools/server/README-dev.md @@ -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. diff --git a/tools/server/public/index.html b/tools/server/public/index.html new file mode 100644 index 0000000000..5767e2045b --- /dev/null +++ b/tools/server/public/index.html @@ -0,0 +1,508 @@ + + + + + + + + + + + +
+ +
+ + diff --git a/tools/server/public/index.html.gz b/tools/server/public/index.html.gz deleted file mode 100644 index adc7939d3b..0000000000 Binary files a/tools/server/public/index.html.gz and /dev/null differ diff --git a/tools/server/server-http.cpp b/tools/server/server-http.cpp index 3466512d0c..69cdb4ecba 100644 --- a/tools/server/server-http.cpp +++ b/tools/server/server-http.cpp @@ -9,7 +9,7 @@ #include // auto generated files (see README.md for details) -#include "index.html.gz.hpp" +#include "index.html.hpp" #include "loading.html.hpp" // @@ -256,16 +256,11 @@ bool server_http_context::init(const common_params & params) { } } else { // 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(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(index_html), index_html_len, "text/html; charset=utf-8"); return false; }); } diff --git a/tools/server/webui/package.json b/tools/server/webui/package.json index f5cdc9e47f..c417638ea4 100644 --- a/tools/server/webui/package.json +++ b/tools/server/webui/package.json @@ -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", diff --git a/tools/server/webui/scripts/install-git-hooks.sh b/tools/server/webui/scripts/install-git-hooks.sh index d14e281389..f4ca3f6eef 100755 --- a/tools/server/webui/scripts/install-git-hooks.sh +++ b/tools/server/webui/scripts/install-git-hooks.sh @@ -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 @@ -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" diff --git a/tools/server/webui/scripts/post-build.sh b/tools/server/webui/scripts/post-build.sh index a49d6cc107..55e46d5d5c 100755 --- a/tools/server/webui/scripts/post-build.sh +++ b/tools/server/webui/scripts/post-build.sh @@ -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 diff --git a/tools/server/webui/vite.config.ts b/tools/server/webui/vite.config.ts index e4408f09e4..af6234b763 100644 --- a/tools/server/webui/vite.config.ts +++ b/tools/server/webui/vite.config.ts @@ -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'; @@ -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() { @@ -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; @@ -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); }