/** * Shared Vite configuration factory for React projects * Following DRY principle - single source of truth for React build configs */ import { defineConfig, mergeConfig, type UserConfig } from 'vite'; import react from '@vitejs/plugin-react'; import * as path from 'path'; /** * Standard alias patterns used across all React apps * Apps can extend but should not duplicate */ const standardAliases = { '@': 'src', '@components': 'src/components', '@features': 'src/features', '@hooks': 'src/hooks', '@providers': 'src/providers', '@routes': 'src/routes', '@lib': 'src/lib', '@config': 'src/config', '@store': 'src/store', '@services': 'src/services', '@types': 'src/types', '@styles': 'src/styles', '@utils': 'src/utils', '@assets': 'src/assets', '@pages': 'src/pages', '@layouts': 'src/layouts', '@api': 'src/api', }; /** * Base Vite configuration for all React applications * Provides sensible defaults that can be overridden */ const baseConfig = defineConfig({ plugins: [react()] as any, // Type assertion to handle Vite version mismatches resolve: { alias: Object.entries(standardAliases).reduce((acc, [key, value]) => { acc[key] = path.resolve(value); return acc; }, {} as Record), }, server: { host: true, cors: true, strictPort: false, }, build: { outDir: 'dist', sourcemap: true, rollupOptions: { output: { manualChunks: { 'react-vendor': ['react', 'react-dom'], 'router': ['react-router-dom'], }, }, }, }, optimizeDeps: { include: ['react', 'react-dom', 'react-router-dom'], }, }); /** * Create a Vite configuration with project-specific overrides * @param overrides - Project-specific configuration to merge * @returns Merged Vite configuration */ export function createViteConfig(overrides: UserConfig = {}): UserConfig { // If overrides has resolve.alias, merge it properly with base aliases if (overrides.resolve?.alias) { const customAliases = overrides.resolve.alias; const mergedAliases = { ...(baseConfig.resolve!.alias as Record) }; // Handle both object and array formats for aliases if (Array.isArray(customAliases)) { customAliases.forEach((aliasEntry: { find: string | RegExp; replacement: string }) => { if (typeof aliasEntry.find === 'string') { mergedAliases[aliasEntry.find] = aliasEntry.replacement; } }); } else { Object.assign(mergedAliases, customAliases); } overrides.resolve.alias = mergedAliases; } return mergeConfig(baseConfig, overrides) as UserConfig; } /** * Export the base config as default for backward compatibility */ export default baseConfig; /** * Export individual parts for advanced use cases */ export { standardAliases, baseConfig };