diff --git a/netlify.toml b/netlify.toml index ab8ce9a..f1829e5 100644 --- a/netlify.toml +++ b/netlify.toml @@ -30,6 +30,7 @@ from = "/*" to = "/index.html" status = 200 +# SPA fallback is handled entirely here so no additional _redirects file is required. [functions] node_bundler = "esbuild" @@ -46,4 +47,30 @@ X-Frame-Options = "DENY" X-XSS-Protection = "1; mode=block" X-Content-Type-Options = "nosniff" - Referrer-Policy = "strict-origin-when-cross-origin" \ No newline at end of file + Referrer-Policy = "strict-origin-when-cross-origin" + Cache-Control = "no-cache, no-store, must-revalidate" + Netlify-CDN-Cache-Control = "no-cache, no-store, must-revalidate" + Pragma = "no-cache" + Expires = "0" + +[[headers]] + for = "/app/*" + [headers.values] + Cache-Control = "no-cache, no-store, must-revalidate" + Netlify-CDN-Cache-Control = "no-cache, no-store, must-revalidate" + Pragma = "no-cache" + Expires = "0" + +[[headers]] + for = "/index.html" + [headers.values] + Cache-Control = "no-cache, no-store, must-revalidate" + Netlify-CDN-Cache-Control = "no-cache, no-store, must-revalidate" + Pragma = "no-cache" + Expires = "0" + +[[headers]] + for = "/assets/*" + [headers.values] + Cache-Control = "public, max-age=31536000, immutable" + Netlify-CDN-Cache-Control = "public, max-age=31536000, immutable" diff --git a/public/_headers b/public/_headers index 923717f..c1a7cd0 100644 --- a/public/_headers +++ b/public/_headers @@ -1,47 +1,61 @@ -# Security headers +# Security headers and disable caching of the SPA shell /* X-Frame-Options: DENY X-XSS-Protection: 1; mode=block X-Content-Type-Options: nosniff Referrer-Policy: strict-origin-when-cross-origin + Netlify-CDN-Cache-Control: no-cache, no-store, must-revalidate Permissions-Policy: geolocation=(), microphone=(), camera=() + Cache-Control: no-cache, no-store, must-revalidate + Pragma: no-cache + Expires: 0 + +# Ensure the app bundles are always served fresh +/app/* + Cache-Control: no-cache, no-store, must-revalidate + Netlify-CDN-Cache-Control: no-cache, no-store, must-revalidate + Pragma: no-cache + Expires: 0 # Cache static assets for 1 year /assets/* Cache-Control: public, max-age=31536000, immutable - -# Cache CSS and JS for 1 month -*.css - Cache-Control: public, max-age=2592000 - -*.js - Cache-Control: public, max-age=2592000 + Netlify-CDN-Cache-Control: public, max-age=31536000, immutable # Cache images for 6 months *.png Cache-Control: public, max-age=15552000 + Netlify-CDN-Cache-Control: public, max-age=15552000 *.jpg Cache-Control: public, max-age=15552000 + Netlify-CDN-Cache-Control: public, max-age=15552000 *.jpeg Cache-Control: public, max-age=15552000 + Netlify-CDN-Cache-Control: public, max-age=15552000 *.gif Cache-Control: public, max-age=15552000 + Netlify-CDN-Cache-Control: public, max-age=15552000 *.svg Cache-Control: public, max-age=15552000 + Netlify-CDN-Cache-Control: public, max-age=15552000 *.webp Cache-Control: public, max-age=15552000 + Netlify-CDN-Cache-Control: public, max-age=15552000 # Cache fonts for 1 year *.woff Cache-Control: public, max-age=31536000 + Netlify-CDN-Cache-Control: public, max-age=31536000 *.woff2 Cache-Control: public, max-age=31536000 + Netlify-CDN-Cache-Control: public, max-age=31536000 *.ttf - Cache-Control: public, max-age=31536000 \ No newline at end of file + Cache-Control: public, max-age=31536000 + Netlify-CDN-Cache-Control: public, max-age=31536000 diff --git a/public/_redirects b/public/_redirects deleted file mode 100644 index eba0dd8..0000000 --- a/public/_redirects +++ /dev/null @@ -1,6 +0,0 @@ -# Redirects for SPA client-side routing -/* /index.html 200 - -# API redirects (these will be handled by Netlify.toml but including for reference) -/api/* http://localhost:3004/api/:splat 200 -/socket.io/* http://localhost:3004/socket.io/:splat 200 \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts index cbee330..7b69910 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -153,73 +153,20 @@ export default defineConfig(({ mode }) => { outDir: 'dist', rollupOptions: { output: { - manualChunks: (id) => { - // Vendor chunks - split large dependencies - if (id.includes('node_modules')) { - if (id.includes('react')) { - return 'react-vendor'; - } - if (id.includes('three')) { - return 'three-vendor'; - } - if (id.includes('@radix-ui')) { - return 'radix-vendor'; - } - if (id.includes('framer-motion')) { - return 'framer-vendor'; - } - if (id.includes('socket.io')) { - return 'socket-vendor'; - } - if (id.includes('recharts') || id.includes('victory')) { - return 'charts-vendor'; - } - // Catch-all for other vendors - return 'vendor'; - } - - // Component chunks - if (id.includes('/components/')) { - if (id.includes('deity')) { - return 'deity-components'; - } - if (id.includes('profile')) { - return 'profile-components'; - } - if (id.includes('sadhana')) { - return 'sadhana-components'; - } - if (id.includes('library')) { - return 'library-components'; - } - if (id.includes('ui/')) { - return 'ui-components'; - } - return 'components'; - } - - // Page chunks - split large landing pages - if (id.includes('/pages/')) { - if (id.includes('landing/')) { - return 'landing-pages'; - } - if (id.includes('user/')) { - return 'user-pages'; - } - return 'pages'; + // Keep the main application bundle names stable so cached HTML never + // references a removed hashed asset after a fresh deployment. + entryFileNames: (chunk) => + chunk.name === "index" ? "app/index.js" : "assets/[name]-[hash].js", + chunkFileNames: "assets/[name]-[hash].js", + assetFileNames: (assetInfo) => { + if (assetInfo.name?.endsWith(".css") && assetInfo.name.startsWith("index")) { + return "app/index.css"; } - - // Hooks and utilities - if (id.includes('/hooks/')) { - return 'hooks'; - } - if (id.includes('/utils/')) { - return 'utils'; - } - if (id.includes('/lib/')) { - return 'lib'; - } - } + return "assets/[name]-[hash][extname]"; + }, + // Allow Vite to manage code-splitting heuristics automatically to avoid + // circular dependencies between manually defined chunks that can cause + // runtime initialization errors in production bundles. } }, // Increase chunk size warning limit