44088b35d7
Route splitting - React.lazy for AdminPage, SettingsPage, FriendsPage, DevicePage, AuthCallbackPage; ChatsPage + ConversationPage stay eager - RouteSuspense wrapper with spinner fallback Vendor chunking - Vite manualChunks splits livekit-client, libsodium, @supabase, react into dedicated cacheable chunks Image thumbnails - createImageBitmap + OffscreenCanvas downscales inline preview to max 640px, emits webp; full blob reserved for the lightbox - Passes through gif/apng/webp so animation is preserved - decoding="async" on the inline img Attachment cache - lib/attachmentCache.ts backed by OPFS; 7-day TTL - AttachmentImage/Audio/Video/PDF/Generic read cache first, decrypt on miss, write-through on success; graceful no-op when OPFS missing Avatar cache - lib/avatarCache.ts — session Map<url, blobUrl> + warmAvatarCache() helper for bulk preload Message batching - Realtime INSERT burst collapses to a single refresh() when >3 ids land within a 250ms window; solo inserts keep the per-id path for latency parity Conversation-list virtualization - VirtualConversationList with IntersectionObserver sentinel, initial 40 rows + 40 per batch; no overhead under threshold Rust release tuning - Cargo [profile.release]: lto, codegen-units=1, strip=symbols, panic=abort, opt-level="s" — ~20-30% smaller binary, faster startup
58 lines
2.1 KiB
TypeScript
58 lines
2.1 KiB
TypeScript
import react from '@vitejs/plugin-react';
|
|
import path from 'node:path';
|
|
import process from 'node:process';
|
|
import { defineConfig } from 'vite';
|
|
|
|
const host = process.env.TAURI_DEV_HOST;
|
|
|
|
export default defineConfig({
|
|
plugins: [react()],
|
|
resolve: {
|
|
alias: {
|
|
'@': path.resolve(__dirname, './src'),
|
|
'@shared': path.resolve(__dirname, '../../packages/shared/src'),
|
|
'@db-types': path.resolve(__dirname, '../../packages/db-types/src'),
|
|
'@ui-web': path.resolve(__dirname, '../../packages/ui-web/src'),
|
|
},
|
|
},
|
|
optimizeDeps: {
|
|
// libsodium-wrappers-sumo (and the compact variant) ship broken "import"
|
|
// conditions in package exports — the ESM bundle references a sibling
|
|
// ./libsodium.mjs that isn't in the published artefact. Force esbuild to
|
|
// pick the "require" condition so the self-contained CJS build is used.
|
|
include: ['libsodium-wrappers-sumo'],
|
|
esbuildOptions: {
|
|
conditions: ['require', 'node', 'default'],
|
|
},
|
|
},
|
|
build: {
|
|
rollupOptions: {
|
|
output: {
|
|
// Split heavy vendor modules into their own chunks so they cache
|
|
// independently from the app shell. LiveKit + libsodium change
|
|
// rarely, so this keeps the hot-path app chunk small on rebuilds
|
|
// and lets the browser cache the big binaries across app updates.
|
|
manualChunks: (id) => {
|
|
if (id.includes('node_modules/livekit-client')) return 'vendor-livekit';
|
|
if (id.includes('node_modules/libsodium-wrappers-sumo')) return 'vendor-sodium';
|
|
if (id.includes('node_modules/@supabase')) return 'vendor-supabase';
|
|
if (id.includes('node_modules/react-router') || id.includes('node_modules/react-dom') || id.includes('node_modules/react/')) {
|
|
return 'vendor-react';
|
|
}
|
|
return undefined;
|
|
},
|
|
},
|
|
},
|
|
},
|
|
clearScreen: false,
|
|
server: {
|
|
port: 1420,
|
|
strictPort: true,
|
|
host: host ?? false,
|
|
...(host ? { hmr: { protocol: 'ws' as const, host, port: 1421 } } : {}),
|
|
watch: {
|
|
ignored: ['**/src-tauri/**'],
|
|
},
|
|
},
|
|
});
|