| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- 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({
- build: {
- chunkSizeWarningLimit: 3072
- },
- 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'
- }
- }
- });
|