Files
SIB/frontend/vite.config.ts

159 lines
5.1 KiB
TypeScript

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { VitePWA } from 'vite-plugin-pwa'
import tailwindcss from '@tailwindcss/vite'
import path from 'path'
import { visualizer } from 'rollup-plugin-visualizer'
// https://vite.dev/config/
export default defineConfig(() => {
return {
plugins: [
vue(),
tailwindcss(),
visualizer({
open: false,
filename: 'dist/stats.html',
gzipSize: true,
brotliSize: true
}),
VitePWA({
selfDestroying: true,
registerType: 'autoUpdate',
includeAssets: ['icono.png', 'icon-192.png', 'icon-512.png', 'icon-1024.png', 'favicon.ico'],
manifest: {
name: 'SIB - Sistema de Transporte',
short_name: 'SIB',
description: 'Sistema de Transporte Público',
theme_color: '#fee715',
background_color: '#ffffff',
display: 'standalone',
orientation: 'portrait',
scope: '/',
start_url: '/splash',
icons: [
{
src: 'icono.png',
sizes: '192x192',
type: 'image/png',
purpose: 'any maskable'
},
{
src: 'icono.png',
sizes: '512x512',
type: 'image/png',
},
{
src: 'icono.png',
sizes: '1024x1024',
type: 'image/png',
},
],
},
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff2}'],
// ⚡ EVITA LAS PANTALLAS BLANCAS: No cachees el backend u orígenes API
navigateFallbackDenylist: [/^\/api/, /^\/rest\/v1/],
runtimeCaching: [
{
urlPattern: /^https:\/\/maps\.googleapis\.com\/.*/i,
handler: 'CacheFirst',
options: {
cacheName: 'google-maps-cache',
expiration: { maxEntries: 50, maxAgeSeconds: 604800 }
}
},
{
urlPattern: /^https:\/\/.*\.supabase\.co\/rest\/v1\/(routes|bus_stops|businesses).*/i,
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'supabase-static-cache',
expiration: { maxEntries: 30, maxAgeSeconds: 300 }
}
},
{
urlPattern: /^https:\/\/.*\.supabase\.co\/rest\/v1\/.*/i,
handler: 'NetworkFirst',
options: {
cacheName: 'supabase-dynamic-cache',
networkTimeoutSeconds: 5,
expiration: { maxEntries: 50, maxAgeSeconds: 60 }
}
},
{
urlPattern: /^https:\/\/.*\.supabase\.co\/storage\/.*/i,
handler: 'CacheFirst',
options: {
cacheName: 'supabase-images-cache',
expiration: { maxEntries: 200, maxAgeSeconds: 2592000 },
cacheableResponse: {
statuses: [0, 200]
}
}
},
{
urlPattern: /^https:\/\/fonts\.(?:googleapis|gstatic)\.com\/.*/i,
handler: 'CacheFirst',
options: {
cacheName: 'google-fonts',
expiration: { maxEntries: 10, maxAgeSeconds: 60 * 60 * 24 * 365 },
cacheableResponse: { statuses: [0, 200] },
}
}
],
},
devOptions: {
enabled: false,
type: 'module',
},
}),
],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
build: {
// Ajustar límite de advertencia (MapView + Google Maps son grandes por naturaleza)
chunkSizeWarningLimit: 700,
rollupOptions: {
output: {
// Dividir código en chunks lógicos para cargas más rápidas en producción
manualChunks: (id) => {
// Vendor: Charts y PDF (solo usados en vistas de Admin)
if (id.includes('node_modules/chart.js') || id.includes('node_modules/vue-chartjs')) {
return 'vendor-charts'
}
if (id.includes('node_modules/jspdf') || id.includes('node_modules/html2canvas')) {
return 'vendor-pdf'
}
// Vendor: Ecosistema Vue (vue, pinia, router, i18n)
if (
id.includes('node_modules/vue') ||
id.includes('node_modules/pinia') ||
id.includes('node_modules/vue-router') ||
id.includes('node_modules/vue-i18n')
) {
return 'vendor-vue'
}
// Vendor: Google Maps loader
if (id.includes('node_modules/@googlemaps')) {
return 'vendor-maps'
}
if (id.includes('node_modules/@supabase/supabase-js')) {
return 'vendor-supabase'
}
},
},
},
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
}
},
},
}
})