mirror of
https://github.com/dergigi/boris.git
synced 2025-12-17 06:34:24 +01:00
debug: add comprehensive logging for image caching
Add debug logs prefixed with [image-preload], [image-cache], [sw-image-cache], and [reader-header] to track: - When images are preloaded - Service Worker availability and controller status - Image fetch success/failure - Service Worker intercepting and caching image requests - Image loading in ReaderHeader component - Cache hits/misses in Service Worker This will help debug why images aren't available offline.
This commit is contained in:
@@ -37,6 +37,17 @@ const ReaderHeader: React.FC<ReaderHeaderProps> = ({
|
|||||||
onHighlightCountClick
|
onHighlightCountClick
|
||||||
}) => {
|
}) => {
|
||||||
const cachedImage = useImageCache(image)
|
const cachedImage = useImageCache(image)
|
||||||
|
|
||||||
|
// Debug: Log image loading state
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (image) {
|
||||||
|
console.log('[reader-header] Image provided:', image)
|
||||||
|
if (cachedImage) {
|
||||||
|
console.log('[reader-header] Using cached image URL:', cachedImage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [image, cachedImage])
|
||||||
|
|
||||||
const { textColor } = useAdaptiveTextColor(cachedImage)
|
const { textColor } = useAdaptiveTextColor(cachedImage)
|
||||||
const formattedDate = published ? format(new Date(published * 1000), 'MMM d, yyyy') : null
|
const formattedDate = published ? format(new Date(published * 1000), 'MMM d, yyyy') : null
|
||||||
const isLongSummary = summary && summary.length > 150
|
const isLongSummary = summary && summary.length > 150
|
||||||
@@ -80,7 +91,21 @@ const ReaderHeader: React.FC<ReaderHeaderProps> = ({
|
|||||||
<>
|
<>
|
||||||
<div className="reader-hero-image">
|
<div className="reader-hero-image">
|
||||||
{cachedImage ? (
|
{cachedImage ? (
|
||||||
<img src={cachedImage} alt={title || 'Article image'} />
|
<img
|
||||||
|
src={cachedImage}
|
||||||
|
alt={title || 'Article image'}
|
||||||
|
onLoad={() => {
|
||||||
|
console.log('[reader-header] ✅ Image loaded successfully:', cachedImage)
|
||||||
|
}}
|
||||||
|
onError={(e) => {
|
||||||
|
console.error('[reader-header] ❌ Image failed to load:', cachedImage, {
|
||||||
|
error: e,
|
||||||
|
target: e.currentTarget,
|
||||||
|
naturalWidth: e.currentTarget.naturalWidth,
|
||||||
|
naturalHeight: e.currentTarget.naturalHeight
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="reader-hero-placeholder">
|
<div className="reader-hero-placeholder">
|
||||||
<FontAwesomeIcon icon={faNewspaper} />
|
<FontAwesomeIcon icon={faNewspaper} />
|
||||||
|
|||||||
@@ -12,6 +12,34 @@ export function useImageCache(
|
|||||||
// Service Worker handles everything - just return the URL as-is
|
// Service Worker handles everything - just return the URL as-is
|
||||||
// The Service Worker will intercept fetch requests and cache them
|
// The Service Worker will intercept fetch requests and cache them
|
||||||
// Make sure images use standard <img src> tags for SW interception
|
// Make sure images use standard <img src> tags for SW interception
|
||||||
|
|
||||||
|
// Debug: Log when image URL is provided
|
||||||
|
if (imageUrl) {
|
||||||
|
console.log('[image-cache] useImageCache hook called with URL:', imageUrl)
|
||||||
|
|
||||||
|
// Check if Service Worker is available
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
if (navigator.serviceWorker.controller) {
|
||||||
|
console.log('[image-cache] ✅ Service Worker controller is active')
|
||||||
|
} else {
|
||||||
|
console.warn('[image-cache] ⚠️ Service Worker not controlling page - checking registration...')
|
||||||
|
navigator.serviceWorker.getRegistration().then((reg) => {
|
||||||
|
if (reg) {
|
||||||
|
console.log('[image-cache] Service Worker registered but not controlling:', {
|
||||||
|
active: !!reg.active,
|
||||||
|
installing: !!reg.installing,
|
||||||
|
waiting: !!reg.waiting
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.warn('[image-cache] ❌ No Service Worker registration found')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn('[image-cache] ❌ Service Workers not supported in this browser')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return imageUrl
|
return imageUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,18 +62,49 @@ export function useCacheImageOnLoad(
|
|||||||
* images are cached before going offline
|
* images are cached before going offline
|
||||||
*/
|
*/
|
||||||
export function preloadImage(imageUrl: string | undefined): void {
|
export function preloadImage(imageUrl: string | undefined): void {
|
||||||
if (!imageUrl) return
|
if (!imageUrl) {
|
||||||
|
console.log('[image-preload] Skipping - no image URL provided')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('[image-preload] Preloading image:', imageUrl)
|
||||||
|
|
||||||
|
// Check if Service Worker is available
|
||||||
|
if ('serviceWorker' in navigator && navigator.serviceWorker.controller) {
|
||||||
|
console.log('[image-preload] ✅ Service Worker is active')
|
||||||
|
} else {
|
||||||
|
console.warn('[image-preload] ⚠️ Service Worker not active - images may not cache')
|
||||||
|
}
|
||||||
|
|
||||||
// Create a link element with rel=prefetch or use Image object to trigger fetch
|
// Create a link element with rel=prefetch or use Image object to trigger fetch
|
||||||
// Service Worker will intercept and cache the request
|
// Service Worker will intercept and cache the request
|
||||||
const img = new Image()
|
const img = new Image()
|
||||||
|
|
||||||
|
img.onload = () => {
|
||||||
|
console.log('[image-preload] ✅ Image loaded successfully:', imageUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
img.onerror = (err) => {
|
||||||
|
console.error('[image-preload] ❌ Image failed to load:', imageUrl, err)
|
||||||
|
}
|
||||||
|
|
||||||
img.src = imageUrl
|
img.src = imageUrl
|
||||||
|
console.log('[image-preload] Created Image() object with src:', imageUrl)
|
||||||
|
|
||||||
// Also try using fetch to explicitly trigger Service Worker
|
// Also try using fetch to explicitly trigger Service Worker
|
||||||
// This ensures the image is cached even if <img> tag hasn't rendered yet
|
// This ensures the image is cached even if <img> tag hasn't rendered yet
|
||||||
fetch(imageUrl, { mode: 'no-cors' }).catch(() => {
|
fetch(imageUrl, { mode: 'no-cors' })
|
||||||
// Ignore errors - image might not be CORS-enabled, but SW will still cache it
|
.then((response) => {
|
||||||
// The Image() approach above will work for most cases
|
console.log('[image-preload] ✅ Fetch successful for image:', imageUrl, {
|
||||||
})
|
status: response.status,
|
||||||
|
type: response.type,
|
||||||
|
url: response.url
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.warn('[image-preload] ⚠️ Fetch failed (may be CORS issue, Image() should still work):', imageUrl, err)
|
||||||
|
// Ignore errors - image might not be CORS-enabled, but SW will still cache it
|
||||||
|
// The Image() approach above will work for most cases
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
32
src/sw.ts
32
src/sw.ts
@@ -31,6 +31,15 @@ registerRoute(
|
|||||||
/\.(jpg|jpeg|png|gif|webp|svg)$/i.test(url.pathname)
|
/\.(jpg|jpeg|png|gif|webp|svg)$/i.test(url.pathname)
|
||||||
// Cache all images, not just cross-origin ones
|
// Cache all images, not just cross-origin ones
|
||||||
// This ensures article images from any source get cached
|
// This ensures article images from any source get cached
|
||||||
|
|
||||||
|
if (isImage) {
|
||||||
|
console.log('[sw-image-cache] Intercepting image request:', {
|
||||||
|
url: url.href,
|
||||||
|
destination: request.destination,
|
||||||
|
method: request.method
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return isImage
|
return isImage
|
||||||
},
|
},
|
||||||
new StaleWhileRevalidate({
|
new StaleWhileRevalidate({
|
||||||
@@ -43,6 +52,29 @@ registerRoute(
|
|||||||
new CacheableResponsePlugin({
|
new CacheableResponsePlugin({
|
||||||
statuses: [0, 200],
|
statuses: [0, 200],
|
||||||
}),
|
}),
|
||||||
|
{
|
||||||
|
cacheKeyWillBeUsed: async ({ request }) => {
|
||||||
|
console.log('[sw-image-cache] Cache key generated for:', request.url)
|
||||||
|
return request
|
||||||
|
},
|
||||||
|
cacheWillUpdate: async ({ response }) => {
|
||||||
|
console.log('[sw-image-cache] Caching response:', {
|
||||||
|
url: response.url,
|
||||||
|
status: response.status,
|
||||||
|
type: response.type,
|
||||||
|
ok: response.ok
|
||||||
|
})
|
||||||
|
return response.ok ? response : null
|
||||||
|
},
|
||||||
|
cachedResponseWillBeUsed: async ({ cachedResponse, request }) => {
|
||||||
|
if (cachedResponse) {
|
||||||
|
console.log('[sw-image-cache] ✅ Serving from cache:', request.url)
|
||||||
|
} else {
|
||||||
|
console.log('[sw-image-cache] ❌ No cached response found:', request.url)
|
||||||
|
}
|
||||||
|
return cachedResponse || null
|
||||||
|
}
|
||||||
|
}
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user