veza/apps/web/vite.config.ts
senke 7b39efa176 fix: stabilize frontend — 98 TS errors to 0, align API endpoints, optimize bundle
- Fix 98 TypeScript errors across 37 files:
  - Service layer double-unwrapping (subscriptionService, distributionService, gearService)
  - Self-referencing variables in SearchPageResults
  - FeedView/ExploreView .posts→.items alignment
  - useQueueSync Zustand subscribe API
  - AdminAuditLogsView missing interface fields
  - Toast proxy type, interceptor type narrowing
  - 22 unused imports/variables removed
  - 5 storybook mock data fixes

- Align frontend API calls with backend endpoints:
  - Analytics: useAnalyticsView now calls /creator/analytics/dashboard (was /analytics)
  - Chat: chatService uses /conversations (was mock data), WS URL from backend token
  - Dashboard StatsSection: uses real /dashboard API data (was hardcoded zeros)
  - Settings: suppress 2FA toast error when endpoint unavailable

- Fix marketplace products: seed uses 'active' status (was 'published')
- Enrich seed: admin follows all creators (feed has content)

- Optimize bundle: vendor catch-all 793KB→318KB gzip (-60%)
  Split into vendor-charts, vendor-emoji, vendor-swagger, vendor-media, etc.

- Clean repo: remove ~100 orphaned screenshots, audit reports, logs from root

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:18:49 +01:00

145 lines
No EOL
5.7 KiB
TypeScript

/// <reference types="vitest" />
import { defineConfig, loadEnv, type Plugin } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'
import { visualizer } from 'rollup-plugin-visualizer'
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
const isProduction = mode === 'production'
const projectRoot = path.resolve(__dirname)
// Load VITE_DOMAIN from .env files (single source of truth for the domain)
const envVars = loadEnv(mode, projectRoot, 'VITE_')
const domain = envVars.VITE_DOMAIN || 'veza.fr'
const backendPort = envVars.VITE_BACKEND_PORT || '18080'
const chatPort = envVars.VITE_CHAT_PORT || '18081'
const streamPort = envVars.VITE_STREAM_PORT || '18082'
return {
// Ensure dev server and dep scan use apps/web only (avoid picking up storybook-static when run from monorepo root)
root: projectRoot,
plugins: [
react(),
// Bundle analyzer for production builds
(isProduction && visualizer({
filename: 'dist/bundle-analysis.html',
open: false,
gzipSize: true,
brotliSize: true,
})) as Plugin,
].filter(Boolean),
test: {
globals: true,
environment: 'jsdom',
setupFiles: './src/setupTests.ts',
css: true,
},
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components'),
'@features': path.resolve(__dirname, './src/features'),
'@services': path.resolve(__dirname, './src/services'),
'@hooks': path.resolve(__dirname, './src/hooks'),
'@utils': path.resolve(__dirname, './src/utils'),
'@types': path.resolve(__dirname, './src/types'),
},
},
server: {
port: parseInt(process.env.PORT || '5173', 10),
host: true,
// Allow dev access via the configured domain (VITE_DOMAIN in .env.local)
allowedHosts: [domain],
// Exclude Storybook build output from watch and fs access so dep scan never touches it
watch: {
ignored: ['**/storybook-static/**', '**/dist_verification/**'],
},
fs: {
deny: ['**/storybook-static/**', '**/dist_verification/**'],
},
// P2.1: Proxy API and Swagger requests to backend in development
// This eliminates CORS issues in dev by making all requests same-origin
proxy: {
'/api': {
target: `http://${domain}:${backendPort}`,
changeOrigin: true,
secure: false,
ws: true,
},
'/swagger': {
target: `http://${domain}:${backendPort}`,
changeOrigin: true,
secure: false,
},
'/ws': {
target: `http://${domain}:${backendPort}`,
changeOrigin: true,
ws: true,
rewrite: (path: string) => path.replace(/^\/ws/, '/api/v1/ws'),
},
'/stream': {
target: `http://${domain}:${streamPort}`,
changeOrigin: true,
ws: true,
},
'/hls': {
target: `http://${domain}:${streamPort}`,
changeOrigin: true,
secure: false,
},
},
},
build: {
outDir: 'dist_verification',
sourcemap: isProduction ? 'hidden' : true,
target: 'esnext',
minify: 'esbuild',
rollupOptions: {
output: {
manualChunks: (id) => {
// Core Vendors
if (id.includes('node_modules/react/') ||
id.includes('node_modules/react-dom/') ||
id.includes('node_modules/react/jsx-runtime')) {
return 'vendor-react';
}
if (id.includes('node_modules')) {
if (id.includes('react-router')) return 'vendor-router';
if (id.includes('@tanstack')) return 'vendor-tanstack';
if (id.includes('lucide-react')) return 'vendor-icons';
if (id.includes('date-fns')) return 'vendor-utils';
if (id.includes('zod')) return 'vendor-utils';
if (id.includes('framer-motion')) return 'vendor-motion';
if (id.includes('dompurify')) return 'vendor-security';
if (id.includes('axios')) return 'vendor-http';
if (id.includes('i18next')) return 'vendor-i18n';
// Lazy-loaded heavy deps — split from catch-all
if (id.includes('recharts') || id.includes('d3-')) return 'vendor-charts';
if (id.includes('@radix-ui')) return 'vendor-radix';
if (id.includes('zustand') || id.includes('immer')) return 'vendor-state';
if (id.includes('@dnd-kit')) return 'vendor-dnd';
if (id.includes('react-hook-form') || id.includes('@hookform')) return 'vendor-forms';
if (id.includes('emoji-picker-react')) return 'vendor-emoji';
if (id.includes('hls.js')) return 'vendor-media';
if (id.includes('@sentry')) return 'vendor-sentry';
if (id.includes('swagger-ui')) return 'vendor-swagger';
if (id.includes('@juspay-tech') || id.includes('hyper')) return 'vendor-payments';
if (id.includes('react-hot-toast')) return 'vendor-toast';
if (id.includes('react-dropzone')) return 'vendor-dropzone';
if (id.includes('class-variance-authority') || id.includes('clsx') || id.includes('tailwind-merge')) return 'vendor-styling';
return 'vendor'; // Remaining small deps
}
},
},
},
chunkSizeWarningLimit: 1000,
},
// Standard optimization settings usually work best
optimizeDeps: {
include: ['react', 'react-dom'],
// Only scan from app entry; avoid storybook-static (and other build outputs) being picked up as entries
entries: ['index.html', 'src/main.tsx'],
},
}
})