From da7e3ba27cb39fa8caa4331abb893ad760ac2871 Mon Sep 17 00:00:00 2001 From: Vaibhav Kumar <69289977+subham9898@users.noreply.github.com> Date: Wed, 12 Nov 2025 00:37:20 +0530 Subject: [PATCH 1/3] Disable caching of SPA shell across routes --- netlify.toml | 17 +++++++++++- public/_headers | 14 ++++------ vite.config.ts | 70 +++---------------------------------------------- 3 files changed, 24 insertions(+), 77 deletions(-) diff --git a/netlify.toml b/netlify.toml index ab8ce9a..7318d4b 100644 --- a/netlify.toml +++ b/netlify.toml @@ -46,4 +46,19 @@ 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" + Pragma = "no-cache" + Expires = "0" + +[[headers]] + for = "/index.html" + [headers.values] + 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" diff --git a/public/_headers b/public/_headers index 923717f..47777fc 100644 --- a/public/_headers +++ b/public/_headers @@ -1,22 +1,18 @@ -# 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 Permissions-Policy: geolocation=(), microphone=(), camera=() + 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 - # Cache images for 6 months *.png Cache-Control: public, max-age=15552000 @@ -44,4 +40,4 @@ 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 diff --git a/vite.config.ts b/vite.config.ts index cbee330..40ec777 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -153,73 +153,9 @@ 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'; - } - - // Hooks and utilities - if (id.includes('/hooks/')) { - return 'hooks'; - } - if (id.includes('/utils/')) { - return 'utils'; - } - if (id.includes('/lib/')) { - return 'lib'; - } - } + // 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 From e453a67058a1edeca9dbb38f99edc0002f0744e3 Mon Sep 17 00:00:00 2001 From: Vaibhav Kumar <69289977+subham9898@users.noreply.github.com> Date: Thu, 13 Nov 2025 13:30:23 +0530 Subject: [PATCH 2/3] Stop caching HTML at Netlify edge --- netlify.toml | 4 ++++ public/_headers | 11 +++++++++++ public/_redirects | 6 ------ 3 files changed, 15 insertions(+), 6 deletions(-) delete mode 100644 public/_redirects diff --git a/netlify.toml b/netlify.toml index 7318d4b..dab18c1 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" @@ -48,6 +49,7 @@ X-Content-Type-Options = "nosniff" 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" @@ -55,6 +57,7 @@ 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" @@ -62,3 +65,4 @@ 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 47777fc..19053f0 100644 --- a/public/_headers +++ b/public/_headers @@ -4,6 +4,7 @@ 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 @@ -12,32 +13,42 @@ # Cache static assets for 1 year /assets/* Cache-Control: public, max-age=31536000, immutable + 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 + 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 From b5d399ec5b1481cb792f5aaa4b3255ca6c359a52 Mon Sep 17 00:00:00 2001 From: Vaibhav Kumar <69289977+subham9898@users.noreply.github.com> Date: Thu, 13 Nov 2025 14:00:05 +0530 Subject: [PATCH 3/3] Serve app bundles without hash filenames --- netlify.toml | 8 ++++++++ public/_headers | 7 +++++++ vite.config.ts | 11 +++++++++++ 3 files changed, 26 insertions(+) diff --git a/netlify.toml b/netlify.toml index dab18c1..f1829e5 100644 --- a/netlify.toml +++ b/netlify.toml @@ -53,6 +53,14 @@ 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] diff --git a/public/_headers b/public/_headers index 19053f0..c1a7cd0 100644 --- a/public/_headers +++ b/public/_headers @@ -10,6 +10,13 @@ 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 diff --git a/vite.config.ts b/vite.config.ts index 40ec777..7b69910 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -153,6 +153,17 @@ export default defineConfig(({ mode }) => { outDir: 'dist', rollupOptions: { output: { + // 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"; + } + 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.