import { defineConfig, loadEnv } from 'vite' import react from '@vitejs/plugin-react' import path from 'path' import { VitePWA } from 'vite-plugin-pwa' // import { fetchTenantNames } from './src/services/tenants' export default defineConfig(async ({ mode }) => { const env = loadEnv(mode, process.cwd(), '') const apiUrl = env.VITE_API_URL const baseDomains = ['sozsoft.com', 'dev.sozsoft.com', '.sozsoft.com'] // const tenantNames = (await fetchTenantNames(apiUrl)).map((n) => n.trim().toLowerCase()) // const tenantHosts = tenantNames.map((t) => `${t}.sozsoft.com`) const tenantHosts: string[] = [] const allowedHosts = Array.from(new Set(['localhost', ...baseDomains, ...tenantHosts])) console.log('> [vite] allowedHosts:', allowedHosts) return { plugins: [ react(), VitePWA({ // Deploy'dan sonra otomatik güncelle registerType: 'autoUpdate', // Kayıt kodunu otomatik enjekte et (virtual:pwa-register yazmadan da çalışır) injectRegister: 'auto', // Dev ortamında SW'yi aç, prod'da kapalı tut (build edilmiş SW prod'da zaten aktif olur) devOptions: { enabled: mode !== 'production', type: 'module', // Modern module worker kullan }, workbox: { // Büyük asset'leri de cache'leyebil maximumFileSizeToCacheInBytes: 10 * 1024 * 1024, // EN KRİTİK: yeni SW beklemeden kontrolü alsın clientsClaim: true, skipWaiting: true, // Eski workbox cache'lerini temizle cleanupOutdatedCaches: true, // SPA fallback'i API çağrılarına uygulama navigateFallbackDenylist: [/^\/api\//], // ⭐⭐ BU KISMI EKLEYİN: Cache sorununu çözecek runtime caching runtimeCaching: mode === 'production' ? [ { urlPattern: /\.(?:js|css|html|json)$/, handler: 'NetworkFirst', options: { cacheName: 'static-resources', expiration: { maxEntries: 50, maxAgeSeconds: 24 * 60 * 60, // 24 saat }, cacheableResponse: { statuses: [0, 200], }, }, }, { urlPattern: /\.(?:png|jpg|jpeg|svg|gif|webp|ico)$/, handler: 'CacheFirst', options: { cacheName: 'images', expiration: { maxEntries: 100, maxAgeSeconds: 30 * 24 * 60 * 60, // 30 gün }, }, }, ] : [], // ⭐ YENİ EKLENEN: Additional navigation route for SPA navigateFallback: '/index.html', navigateFallbackAllowlist: [/^(?!\/__).*/], }, manifest: { name: 'Sözsoft Kurs Platform', short_name: 'Sözsoft Kurs Platform', theme_color: '#FF99C8', background_color: '#f0e7db', display: 'standalone', icons: [ { src: '/img/logo/logo-400.png', sizes: '400x400', type: 'image/png', purpose: 'any maskable', }, { src: '/img/logo/logo-192.png', sizes: '192x192', type: 'image/png', purpose: 'any maskable', }, { src: '/img/logo/logo-512.png', sizes: '512x512', type: 'image/png', purpose: 'any maskable', }, ], categories: ['business', 'productivity'], description: 'Sözsoft Kurs Platform Application', }, }), ], server: { open: true, port: 3000, // ⭐ YENİ EKLENEN: Hot reload için polling watch: { usePolling: true, interval: 1000, }, }, assetsInclude: ['**/*.md'], resolve: { alias: { '@': path.join(__dirname, 'src'), inferno: 'inferno/dist/index.esm.js', 'devextreme/ui': 'devextreme/esm/ui', }, }, build: { outDir: 'dist', sourcemap: false, emptyOutDir: true, rollupOptions: { output: { entryFileNames: `assets/[name].[hash].js`, chunkFileNames: `assets/[name].[hash].js`, assetFileNames: `assets/[name].[hash].[ext]`, }, }, }, preview: { host: '0.0.0.0', port: 80, open: false, // Hesaplanan allowedHosts'u kullan allowedHosts, }, define: { 'process.env': {}, // ⭐ YENİ EKLENEN: Version tracking için global değişkenler __APP_VERSION__: JSON.stringify(process.env.VITE_APP_VERSION || '1.0.0'), __BUILD_DATE__: JSON.stringify(new Date().toISOString()), __APP_MODE__: JSON.stringify(mode), }, } })