portfolio : remove preloadAll, use {#key} for clean project transitions. related to #55
All checks were successful
Deploy / Deploy to Production (push) Successful in 21s

preloadAll caused slow loading by fetching all projects' images at once
(and 404s from srcset strings used as img src). {#key currentIndex}
destroys/recreates DOM on project switch, eliminating stale images.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
isUnknown 2026-04-03 11:58:06 +02:00
parent 947275544d
commit 3c92903518

View file

@ -128,28 +128,12 @@
} }
}) })
// --- Préchargement de tous les médias au premier passage ---
let preloaded = false
function preloadAll() {
for (const project of projects) {
if (project.mockup) new Image().src = project.mockup
if (project.mockupWebp) new Image().src = project.mockupWebp
if (project.galleryBackgroundImage) new Image().src = project.galleryBackgroundImage
for (const img of (project.imagesGallery ?? [])) {
if (img.src) new Image().src = img.src
if (img.webp) new Image().src = img.webp
}
}
}
// --- Effect: reset when slide deactivated --- // --- Effect: reset when slide deactivated ---
// wasActive évite que clearAnchor() s'exécute au montage initial // wasActive évite que clearAnchor() s'exécute au montage initial
// (isActive est false avant l'initialisation des slides) // (isActive est false avant l'initialisation des slides)
let wasActive = false let wasActive = false
$effect(() => { $effect(() => {
if (isActive) { if (isActive) {
if (!preloaded) { preloaded = true; preloadAll() }
wasActive = true wasActive = true
} else if (wasActive) { } else if (wasActive) {
nav.reset() nav.reset()
@ -162,9 +146,11 @@
}) })
</script> </script>
{#key currentIndex}
<div class="portfolio-gallery mobile-only" aria-hidden="true"> <div class="portfolio-gallery mobile-only" aria-hidden="true">
<GalleryAnimation images={currentProject.imagesGallery} backgroundColor={currentProject.galleryBackgroundColor} backgroundImage={currentProject.galleryBackgroundImage} mode={currentProject.galleryAnimationMode} secondsPerImage={currentProject.secondsPerImage} /> <GalleryAnimation images={currentProject.imagesGallery} backgroundColor={currentProject.galleryBackgroundColor} backgroundImage={currentProject.galleryBackgroundImage} mode={currentProject.galleryAnimationMode} secondsPerImage={currentProject.secondsPerImage} />
</div> </div>
{/key}
<section <section
class="portfolio golden-grid" class="portfolio golden-grid"
@ -173,40 +159,42 @@
aria-label="Portfolio" aria-label="Portfolio"
> >
{#if currentProject} {#if currentProject}
<!-- Galerie animation (gauche desktop / plein écran mobile) --> {#key currentIndex}
<div class="portfolio-gallery desktop-only" aria-hidden="true"> <!-- Galerie animation (gauche desktop / plein écran mobile) -->
<GalleryAnimation images={currentProject.imagesGallery} backgroundColor={currentProject.galleryBackgroundColor} backgroundImage={currentProject.galleryBackgroundImage} mode={currentProject.galleryAnimationMode} secondsPerImage={currentProject.secondsPerImage} /> <div class="portfolio-gallery desktop-only" aria-hidden="true">
</div> <GalleryAnimation images={currentProject.imagesGallery} backgroundColor={currentProject.galleryBackgroundColor} backgroundImage={currentProject.galleryBackgroundImage} mode={currentProject.galleryAnimationMode} secondsPerImage={currentProject.secondsPerImage} />
<!-- Mockup device (centre) -->
<div class="portfolio-mockup portfolio-mockup--{currentProject.galleryAnimationMode}">
<ResponsivePicture
src={currentProject.mockup}
srcset={currentProject.mockupSrcset}
webp={currentProject.mockupWebp}
sizes="(max-width: 700px) 90vw, 25vw"
alt={currentProject.title}
cls="portfolio-mockup-img"
/>
</div>
<img class="content-background mobile-only" src="/assets/img/BG GAME MOBILE.408a3a253492f65d39f8.png" alt="">
<!-- Infos projet (droite) -->
<div class="portfolio-text" aria-live="polite">
<h2>{currentProject.title}</h2>
<h3 class="portfolio-catchphrase gradient-blue">{@html currentProject.catchPhrase}</h3>
<div class="portfolio-description">{@html currentProject.description}</div>
<div class="portfolio-keywords">
{#each currentProject.keywords as kw}
<p><strong>{kw.label} :</strong> {kw.text}</p>
{/each}
</div> </div>
<div class="portfolio-links">
{#each currentProject.externalLinks as link} <!-- Mockup device (centre) -->
<a href={link.url} target="_blank" rel="noopener noreferrer" class="button with-icon earth-icon">{link.label}</a> <div class="portfolio-mockup portfolio-mockup--{currentProject.galleryAnimationMode}">
{/each} <ResponsivePicture
src={currentProject.mockup}
srcset={currentProject.mockupSrcset}
webp={currentProject.mockupWebp}
sizes="(max-width: 700px) 90vw, 25vw"
alt={currentProject.title}
cls="portfolio-mockup-img"
/>
</div> </div>
</div> <img class="content-background mobile-only" src="/assets/img/BG GAME MOBILE.408a3a253492f65d39f8.png" alt="">
<!-- Infos projet (droite) -->
<div class="portfolio-text" aria-live="polite">
<h2>{currentProject.title}</h2>
<h3 class="portfolio-catchphrase gradient-blue">{@html currentProject.catchPhrase}</h3>
<div class="portfolio-description">{@html currentProject.description}</div>
<div class="portfolio-keywords">
{#each currentProject.keywords as kw}
<p><strong>{kw.label} :</strong> {kw.text}</p>
{/each}
</div>
<div class="portfolio-links">
{#each currentProject.externalLinks as link}
<a href={link.url} target="_blank" rel="noopener noreferrer" class="button with-icon earth-icon">{link.label}</a>
{/each}
</div>
</div>
{/key}
{/if} {/if}
<!-- Sidebar navigation --> <!-- Sidebar navigation -->