Files
gamercomp/frontend/vite.config.js
T
2026-04-30 02:14:25 +00:00

147 lines
4.3 KiB
JavaScript

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { VitePWA } from 'vite-plugin-pwa'
// https://vite.dev/config/
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
// Core React dependencies
'vendor-react': ['react', 'react-dom', 'react-router-dom'],
// UI/utility libraries (if any large ones are added)
// Split pages into separate chunks for lazy loading
}
}
},
// Target modern browsers for smaller bundle
target: 'es2020',
// Increase chunk size warning limit
chunkSizeWarningLimit: 600
},
plugins: [
react(),
VitePWA({
registerType: 'autoUpdate',
// Force service worker to update immediately
devOptions: {
enabled: false
},
includeAssets: ['favicon.ico', 'robots.txt'],
manifest: {
name: 'GamerComp',
short_name: 'GamerComp',
description: 'Where kids become Game Composers! Learn AI communication by creating your own games.',
theme_color: '#6366f1',
background_color: '#1e1b4b',
display: 'standalone',
orientation: 'any',
scope: '/',
start_url: '/',
icons: [
{
src: '/icon.svg',
sizes: 'any',
type: 'image/svg+xml',
purpose: 'any'
},
{
src: '/icon.svg',
sizes: '512x512',
type: 'image/svg+xml',
purpose: 'maskable'
}
],
categories: ['games', 'entertainment', 'education'],
screenshots: [
{
src: '/screenshot-wide.png',
sizes: '1280x720',
type: 'image/png',
form_factor: 'wide'
},
{
src: '/screenshot-narrow.png',
sizes: '640x1136',
type: 'image/png',
form_factor: 'narrow'
}
]
},
workbox: {
// Force update without waiting
skipWaiting: true,
clientsClaim: true,
// Import push notification handler
importScripts: ['/push-handler.js'],
// Use network-first for navigation to always get fresh HTML
navigateFallback: 'index.html',
navigateFallbackDenylist: [/^\/api/],
// Cache strategies
runtimeCaching: [
{
// Cache API responses (except play/start which needs to be fresh)
urlPattern: /^https:\/\/gamercomp\.com\/api\/(?!play\/start|auth).*/i,
handler: 'NetworkFirst',
options: {
cacheName: 'api-cache',
expiration: {
maxEntries: 100,
maxAgeSeconds: 60 * 60 // 1 hour
},
cacheableResponse: {
statuses: [0, 200]
}
}
},
{
// Cache game code for offline play
urlPattern: /^https:\/\/gamercomp\.com\/api\/arcade\/games\/\d+$/i,
handler: 'CacheFirst',
options: {
cacheName: 'game-cache',
expiration: {
maxEntries: 50,
maxAgeSeconds: 60 * 60 * 24 * 7 // 1 week
},
cacheableResponse: {
statuses: [0, 200]
}
}
},
{
// Cache fonts
urlPattern: /^https:\/\/fonts\.googleapis\.com\/.*/i,
handler: 'CacheFirst',
options: {
cacheName: 'google-fonts-cache',
expiration: {
maxEntries: 10,
maxAgeSeconds: 60 * 60 * 24 * 365 // 1 year
},
cacheableResponse: {
statuses: [0, 200]
}
}
},
{
// Cache images
urlPattern: /\.(?:png|jpg|jpeg|svg|gif|webp)$/i,
handler: 'CacheFirst',
options: {
cacheName: 'image-cache',
expiration: {
maxEntries: 50,
maxAgeSeconds: 60 * 60 * 24 * 30 // 30 days
}
}
}
],
// Pre-cache essential files
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff2}']
}
})
],
})