feat: Slate & Ice Modern aesthetic redesign #94
@@ -8,12 +8,19 @@ server {
|
||||
gzip on;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
|
||||
# index.html — never cache (so deploys serve new chunk references)
|
||||
location = /index.html {
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
add_header Pragma "no-cache";
|
||||
add_header Expires "0";
|
||||
}
|
||||
|
||||
# Handle SPA routing - serve index.html for all routes
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Cache static assets
|
||||
# Cache hashed static assets (immutable — filenames change on rebuild)
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
|
||||
@@ -1,14 +1,44 @@
|
||||
import { useEffect } from 'react'
|
||||
import { useRouteError, isRouteErrorResponse, useNavigate } from 'react-router-dom'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
function isChunkLoadError(error: unknown): boolean {
|
||||
if (!(error instanceof Error)) return false
|
||||
const msg = error.message.toLowerCase()
|
||||
return (
|
||||
msg.includes('failed to fetch dynamically imported module') ||
|
||||
msg.includes('importing a module script failed') ||
|
||||
msg.includes('loading chunk') ||
|
||||
msg.includes('loading css chunk')
|
||||
)
|
||||
}
|
||||
|
||||
const RELOAD_KEY = 'rf_chunk_reload'
|
||||
|
||||
export function RouteError() {
|
||||
const error = useRouteError()
|
||||
const navigate = useNavigate()
|
||||
|
||||
// Auto-reload once on chunk load failures (stale deploy)
|
||||
useEffect(() => {
|
||||
if (isChunkLoadError(error)) {
|
||||
const lastReload = sessionStorage.getItem(RELOAD_KEY)
|
||||
const now = Date.now()
|
||||
// Only auto-reload if we haven't reloaded in the last 10 seconds (prevent loops)
|
||||
if (!lastReload || now - Number(lastReload) > 10_000) {
|
||||
sessionStorage.setItem(RELOAD_KEY, String(now))
|
||||
window.location.reload()
|
||||
}
|
||||
}
|
||||
}, [error])
|
||||
|
||||
let errorMessage = 'An unexpected error occurred'
|
||||
let errorDetails = ''
|
||||
|
||||
if (isRouteErrorResponse(error)) {
|
||||
if (isChunkLoadError(error)) {
|
||||
errorMessage = 'App Updated'
|
||||
errorDetails = 'A new version was deployed. Please refresh the page.'
|
||||
} else if (isRouteErrorResponse(error)) {
|
||||
errorMessage = error.status === 404 ? 'Page not found' : `Error ${error.status}`
|
||||
errorDetails = error.statusText || ''
|
||||
} else if (error instanceof Error) {
|
||||
|
||||
Reference in New Issue
Block a user