mirror of
				https://github.com/ggml-org/llama.cpp.git
				synced 2025-11-04 09:32:00 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			138 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			138 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import tailwindcss from '@tailwindcss/vite';
 | 
						|
import { sveltekit } from '@sveltejs/kit/vite';
 | 
						|
import * as fflate from 'fflate';
 | 
						|
import { readFileSync, writeFileSync, existsSync } from 'fs';
 | 
						|
import { resolve } from 'path';
 | 
						|
import { defineConfig } from 'vite';
 | 
						|
import devtoolsJson from 'vite-plugin-devtools-json';
 | 
						|
import { storybookTest } from '@storybook/addon-vitest/vitest-plugin';
 | 
						|
 | 
						|
const GUIDE_FOR_FRONTEND = `
 | 
						|
<!--
 | 
						|
  This is a single file build of the frontend.
 | 
						|
  It is automatically generated by the build process.
 | 
						|
  Do not edit this file directly.
 | 
						|
  To make changes, refer to the "Web UI" section in the README.
 | 
						|
-->
 | 
						|
`.trim();
 | 
						|
 | 
						|
const MAX_BUNDLE_SIZE = 2 * 1024 * 1024;
 | 
						|
 | 
						|
function llamaCppBuildPlugin() {
 | 
						|
	return {
 | 
						|
		name: 'llamacpp:build',
 | 
						|
		apply: 'build' as const,
 | 
						|
		closeBundle() {
 | 
						|
			// Ensure the SvelteKit adapter has finished writing to ../public
 | 
						|
			setTimeout(() => {
 | 
						|
				try {
 | 
						|
					const indexPath = resolve('../public/index.html');
 | 
						|
					const gzipPath = resolve('../public/index.html.gz');
 | 
						|
 | 
						|
					if (!existsSync(indexPath)) {
 | 
						|
						return;
 | 
						|
					}
 | 
						|
 | 
						|
					let content = readFileSync(indexPath, 'utf-8');
 | 
						|
 | 
						|
					const faviconPath = resolve('static/favicon.svg');
 | 
						|
					if (existsSync(faviconPath)) {
 | 
						|
						const faviconContent = readFileSync(faviconPath, 'utf-8');
 | 
						|
						const faviconBase64 = Buffer.from(faviconContent).toString('base64');
 | 
						|
						const faviconDataUrl = `data:image/svg+xml;base64,${faviconBase64}`;
 | 
						|
 | 
						|
						content = content.replace(/href="[^"]*favicon\.svg"/g, `href="${faviconDataUrl}"`);
 | 
						|
 | 
						|
						console.log('✓ Inlined favicon.svg as base64 data URL');
 | 
						|
					}
 | 
						|
 | 
						|
					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');
 | 
						|
				} catch (error) {
 | 
						|
					console.error('Failed to create gzip file:', error);
 | 
						|
				}
 | 
						|
			}, 100);
 | 
						|
		}
 | 
						|
	};
 | 
						|
}
 | 
						|
 | 
						|
export default defineConfig({
 | 
						|
	plugins: [tailwindcss(), sveltekit(), devtoolsJson(), llamaCppBuildPlugin()],
 | 
						|
	test: {
 | 
						|
		projects: [
 | 
						|
			{
 | 
						|
				extends: './vite.config.ts',
 | 
						|
				test: {
 | 
						|
					name: 'client',
 | 
						|
					environment: 'browser',
 | 
						|
					browser: {
 | 
						|
						enabled: true,
 | 
						|
						provider: 'playwright',
 | 
						|
						instances: [{ browser: 'chromium' }]
 | 
						|
					},
 | 
						|
					include: ['src/**/*.svelte.{test,spec}.{js,ts}'],
 | 
						|
					exclude: ['src/lib/server/**'],
 | 
						|
					setupFiles: ['./vitest-setup-client.ts']
 | 
						|
				}
 | 
						|
			},
 | 
						|
			{
 | 
						|
				extends: './vite.config.ts',
 | 
						|
				test: {
 | 
						|
					name: 'server',
 | 
						|
					environment: 'node',
 | 
						|
					include: ['src/**/*.{test,spec}.{js,ts}'],
 | 
						|
					exclude: ['src/**/*.svelte.{test,spec}.{js,ts}']
 | 
						|
				}
 | 
						|
			},
 | 
						|
			{
 | 
						|
				extends: './vite.config.ts',
 | 
						|
				test: {
 | 
						|
					name: 'ui',
 | 
						|
					environment: 'browser',
 | 
						|
					browser: {
 | 
						|
						enabled: true,
 | 
						|
						provider: 'playwright',
 | 
						|
						instances: [{ browser: 'chromium', headless: true }]
 | 
						|
					},
 | 
						|
					include: ['src/**/*.stories.{js,ts,svelte}'],
 | 
						|
					setupFiles: ['./.storybook/vitest.setup.ts']
 | 
						|
				},
 | 
						|
				plugins: [
 | 
						|
					storybookTest({
 | 
						|
						storybookScript: 'pnpm run storybook --no-open'
 | 
						|
					})
 | 
						|
				]
 | 
						|
			}
 | 
						|
		]
 | 
						|
	},
 | 
						|
	server: {
 | 
						|
		proxy: {
 | 
						|
			'/v1': 'http://localhost:8080',
 | 
						|
			'/props': 'http://localhost:8080',
 | 
						|
			'/slots': 'http://localhost:8080'
 | 
						|
		},
 | 
						|
		headers: {
 | 
						|
			'Cross-Origin-Embedder-Policy': 'require-corp',
 | 
						|
			'Cross-Origin-Opener-Policy': 'same-origin'
 | 
						|
		}
 | 
						|
	}
 | 
						|
});
 |