Fork of Chiri for Astro for my blog
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf(cache): improve caching strategy

the3ash e50ac229 903241c7

+113 -67
+9 -24
netlify.toml
··· 32 32 default-src 'self'; 33 33 script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; 34 34 style-src 'self' 'unsafe-inline' https:; 35 - img-src 'self' data: https: blob: 'unsafe-inline'; 35 + img-src 'self' data: https: blob:; 36 36 font-src 'self' data: https:; 37 37 frame-src https:; 38 - connect-src 'self' https: blob:; 38 + connect-src 'self' https:; 39 39 object-src 'none'; 40 40 worker-src 'self' blob:; 41 41 child-src 'self' blob:; 42 - media-src 'self' blob:; 43 42 ''' 44 43 45 44 # Static assets caching ··· 73 72 Cache-Control = "public, max-age=31536000, immutable" 74 73 Vary = "Accept-Encoding" 75 74 76 - # HTML caching with revalidation 75 + # HTML caching for static pages 77 76 [[headers]] 78 77 for = "*.html" 79 78 [headers.values] 80 - Cache-Control = "public, max-age=300, s-maxage=3600" 79 + Cache-Control = "public, max-age=3600, s-maxage=7200" 81 80 Vary = "Accept-Encoding" 82 81 83 82 # Image optimization ··· 99 98 Cache-Control = "public, max-age=31536000, immutable" 100 99 Vary = "Accept-Encoding" 101 100 102 - # Favicon - no cache for real-time theme switching 103 - [[headers]] 104 - for = "/favicon.svg" 105 - [headers.values] 106 - Cache-Control = "no-cache, no-store, must-revalidate, max-age=0, s-maxage=0" 107 - Pragma = "no-cache" 108 - Expires = "0" 109 - Vary = "Accept-Encoding" 110 - Surrogate-Control = "no-store" 111 - Surrogate-Key = "favicon" 112 - Access-Control-Allow-Origin = "*" 113 - Access-Control-Allow-Methods = "GET, OPTIONS" 114 - Access-Control-Allow-Headers = "Cache-Control, Pragma" 115 - 116 - # Homepage with resource hints 101 + # Homepage with resource hints and shorter cache 117 102 [[headers]] 118 103 for = "/" 119 104 [headers.values] 120 105 Link = "</fonts/Inter.woff2>; rel=preload; as=font; type=font/woff2; crossorigin=anonymous, </fonts/Besley-Italic.woff2>; rel=preload; as=font; type=font/woff2; crossorigin=anonymous" 121 - Cache-Control = "public, max-age=300, s-maxage=3600" 106 + Cache-Control = "public, max-age=1800, s-maxage=3600" 122 107 Vary = "Accept-Encoding" 123 108 124 - # Article page optimization 109 + # Blog post pages (direct slug routes) 125 110 [[headers]] 126 - for = "/posts/*" 111 + for = "/*/" 127 112 [headers.values] 128 - Cache-Control = "public, max-age=600, s-maxage=3600" 113 + Cache-Control = "public, max-age=7200, s-maxage=14400" 129 114 Vary = "Accept-Encoding" 130 115 131 116 # Enable compression
+104 -43
src/components/ui/TransitionInit.astro
··· 7 7 {fadeAnimation && <meta name="view-transition" content="same-origin" />} 8 8 9 9 <script is:inline define:vars={{ fadeAnimation }}> 10 - // Initialize page transition animation 11 - function initMotionPref(doc = document) { 12 - const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches 13 - const supportsViewTransitions = 'startViewTransition' in document 10 + // Enhanced transition initialization - cache-resistant 11 + ;(() => { 12 + let isInitialized = false 13 + let initCounter = 0 14 14 15 - doc.documentElement.classList.toggle('reduce-motion', prefersReducedMotion) 15 + function initMotionPref(doc = document, force = false) { 16 + // Force re-initialization even if already done 17 + if (!force && isInitialized && initCounter < 3) { 18 + return 19 + } 16 20 17 - doc.documentElement.classList.toggle( 18 - 'disable-transitions', 19 - !fadeAnimation || !supportsViewTransitions 20 - ) 21 + initCounter++ 21 22 22 - // Dynamically control view transition navigation behavior 23 - let viewTransitionStyle = doc.getElementById('view-transition-style') 23 + const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches 24 + const supportsViewTransitions = 'startViewTransition' in document 24 25 25 - if (fadeAnimation && supportsViewTransitions && !prefersReducedMotion) { 26 - // Enable view transition navigation 27 - if (!viewTransitionStyle) { 28 - viewTransitionStyle = doc.createElement('style') 29 - viewTransitionStyle.id = 'view-transition-style' 30 - viewTransitionStyle.textContent = '@view-transition { navigation: auto; }' 31 - doc.head.appendChild(viewTransitionStyle) 32 - } 33 - } else { 34 - // Disable view transition navigation 35 - if (viewTransitionStyle) { 36 - viewTransitionStyle.remove() 26 + doc.documentElement.classList.toggle('reduce-motion', prefersReducedMotion) 27 + doc.documentElement.classList.toggle( 28 + 'disable-transitions', 29 + !fadeAnimation || !supportsViewTransitions 30 + ) 31 + 32 + // Dynamically control view transition navigation behavior 33 + let viewTransitionStyle = doc.getElementById('view-transition-style') 34 + 35 + if (fadeAnimation && supportsViewTransitions && !prefersReducedMotion) { 36 + // Enable view transition navigation 37 + if (!viewTransitionStyle) { 38 + viewTransitionStyle = doc.createElement('style') 39 + viewTransitionStyle.id = 'view-transition-style' 40 + viewTransitionStyle.textContent = '@view-transition { navigation: auto; }' 41 + doc.head.appendChild(viewTransitionStyle) 42 + } 43 + 44 + // Ensure HTML has correct transition attributes 45 + if (!doc.documentElement.hasAttribute('transition:animate')) { 46 + doc.documentElement.setAttribute('transition:animate', 'initial') 47 + } 48 + } else { 49 + // Disable view transition navigation 50 + if (viewTransitionStyle) { 51 + viewTransitionStyle.remove() 52 + } 37 53 } 54 + 55 + doc.documentElement.classList.add('js') 56 + isInitialized = true 38 57 } 39 58 40 - doc.documentElement.classList.add('js') 41 - } 59 + // Initialize motion preferences with force flag 60 + function initAll(doc = document, force = false) { 61 + initMotionPref(doc, force) 62 + } 63 + 64 + // Immediate initialization 65 + initAll(document, true) 66 + 67 + // Astro-specific events 68 + document.addEventListener('astro:before-swap', ({ newDocument }) => { 69 + initAll(newDocument, true) 70 + }) 42 71 43 - // Initialize motion preferences 44 - function initAll(doc = document) { 45 - initMotionPref(doc) 46 - } 72 + document.addEventListener('astro:page-load', () => { 73 + initAll(document, true) 74 + }) 75 + 76 + document.addEventListener('astro:after-swap', () => { 77 + initAll(document, true) 78 + }) 47 79 48 - initAll() 80 + // Browser navigation events 81 + window.addEventListener('pageshow', () => { 82 + // Always re-init on pageshow, especially when coming from cache 83 + initAll(document, true) 84 + }) 49 85 50 - document.addEventListener('astro:before-swap', ({ newDocument }) => { 51 - initAll(newDocument) 52 - }) 86 + window.addEventListener('pagehide', () => { 87 + // Reset state when page is hidden 88 + isInitialized = false 89 + initCounter = 0 90 + }) 53 91 54 - document.addEventListener('astro:page-load', () => { 55 - initAll() 56 - }) 92 + // Page visibility changes 93 + document.addEventListener('visibilitychange', () => { 94 + if (document.visibilityState === 'visible') { 95 + initAll(document, true) 96 + } 97 + }) 57 98 58 - document.addEventListener('visibilitychange', () => { 59 - if (document.visibilityState === 'visible') { 60 - initAll() 99 + // DOM ready states 100 + if (document.readyState === 'loading') { 101 + document.addEventListener('DOMContentLoaded', () => { 102 + initAll(document, true) 103 + }) 61 104 } 62 - }) 63 105 64 - window.addEventListener('pageshow', () => { 65 - initAll() 66 - }) 106 + // Focus events (when user returns to tab) 107 + window.addEventListener('focus', () => { 108 + initAll(document, true) 109 + }) 110 + 111 + // Fallback: periodic check for the first few seconds 112 + let checkCount = 0 113 + const intervalCheck = setInterval(() => { 114 + if (checkCount >= 5) { 115 + clearInterval(intervalCheck) 116 + return 117 + } 118 + 119 + checkCount++ 120 + initAll(document, true) 121 + }, 500) 122 + 123 + // Clean up interval when page unloads 124 + window.addEventListener('beforeunload', () => { 125 + clearInterval(intervalCheck) 126 + }) 127 + })() 67 128 </script>