Composants d'image React Spectrum : stratégies d'optimisation
Les performances de chargement des images influencent directement l'expérience utilisateur et les Core Web Vitals dans les applications web modernes. React Spectrum, la bibliothèque de composants UI open source d'Adobe, propose des composants Image et Avatar professionnels intégrant diverses stratégies d'optimisation.
Caractéristiques principales du composant Image
Utilisation de base
import { Image } from '@react-spectrum/image';
function IllustrationProduit({ produit }) {
return (
<Image
src={produit.urlImage}
alt={produit.nom}
objectFit="cover"
onLoad={(e) => console.log('Image chargée:', e.target)}
onError={(e) => console.error('Échec du chargement:', e.target)}
crossOrigin="anonymous"
/>
);
}
Propriétés principales
| Propriété |
Type |
Description |
| src |
string |
URL de l'image avec support des images responsives |
| alt |
string |
Texte alternatif pour l'accessibilité et le SEO |
| objectFit |
string |
Mode de remplissage de l'image |
| onLoad |
function |
Callback de fin de chargement |
| onError |
function |
Calllback d'erreur de chargement |
| crossOrigin |
string |
Configuraton CORS pour CDN et cache |
Optimisation du composant Avatar
Implémentation standard
import { Avatar } from '@react-spectrum/avatar';
function ProfilUtilisateur({ utilisateur }) {
return (
<Avatar
src={utilisateur.urlAvatar}
alt={utilisateur.nom}
size="avatar-size-300"
isDisabled={!utilisateur.estActif}
/>
);
}
Dimensions standards
| Constante |
Valeur |
Usage |
| avatar-size-50 |
16px |
Icônes minuscules |
| avatar-size-100 |
32px |
Dimension par défaut |
| avatar-size-300 |
64px |
Pages de profil |
| avatar-size-500 |
128px |
Affichages larges |
Techniques d'optimisation avancées
Stratégie de chargement responsive
function ImageOptimisee({ image }) {
const [estChargee, setEstChargee] = useState(false);
const [aErreur, setAErreur] = useState(false);
const gestionChargement = useCallback(() => {
setEstChargee(true);
performance.mark('image-chargee');
}, []);
const gestionErreur = useCallback(() => {
setAErreur(true);
}, []);
return (
<div className={`conteneur-image ${estChargee ? 'chargee' : 'chargement'}`}>
{!estChargee && !aErreur && (
<div className="squelette-image">
{/* Placeholder skeleton */}
</div>
)}
<Image
src={image.src}
srcSet={`${image.src}?largeur=400 400w, ${image.src}?largeur=800 800w`}
sizes="(max-width: 600px) 400px, 800px"
alt={image.alt}
onLoad={gestionChargement}
onError={gestionErreur}
objectFit="cover"
/>
</div>
);
}
Implémentation du lazy loading
import { useInView } from 'react-intersection-observer';
function ImageDifferee({ src, alt, ...props }) {
const [ref, enVue] = useInView({
threshold: 0.1,
triggerOnce: true,
});
return (
<div ref={ref}>
{enVue ? (
<Image
src={src}
alt={alt}
{...props}
/>
) : (
<div className="placeholder-image">
{/* Image de faible qualité (LQIP) */}
</div>
)}
</div>
);
}
Gestion des erreurs et fallback
function AvatarResilient({ utilisateur, ...props }) {
const [srcActuel, setSrcActuel] = useState(utilisateur.urlAvatar);
const [tentatives, setTentatives] = useState(0);
const gestionErreur = useCallback(() => {
if (tentatives < 2) {
setTentatives(prev => prev + 1);
setSrcActuel(`${utilisateur.urlAvatar}?retry=${tentatives + 1}`);
} else {
setSrcActuel('/avatar-par-defaut.png');
}
}, [tentatives, utilisateur.urlAvatar]);
return (
<Avatar
src={srcActuel}
alt={utilisateur.nom}
onError={gestionErreur}
{...props}
/>
);
}
Surveillance des performances
Mesure des indicateurs clés
function usePerformancesImage(src) {
const [metriques, setMetriques] = useState({
tempsChargement: 0,
tempsDebut: 0,
estCache: false
});
useEffect(() => {
const debut = performance.now();
setMetriques(prev => ({ ...prev, tempsDebut: debut }));
const img = new Image();
img.onload = () => {
const tempsChargement = performance.now() - debut;
const estCache = tempsChargement < 50;
setMetriques({
tempsChargement,
tempsDebut: debut,
estCache
});
envoyerMetriquesAnalytics({
urlImage: src,
tempsChargement,
estCache
});
};
img.src = src;
return () => {
img.onload = null;
};
}, [src]);
return metriques;
}
Bonnes pratiques de codage
Exemples recommmandés et à éviter
// ✅ Pratique recommandée
const BonneImage = () => (
<Image
src="https://exemple.com/image.jpg?largeur=400"
srcSet="https://exemple.com/image.jpg?largeur=400 400w, https://exemple.com/image.jpg?largeur=800 800w"
sizes="(max-width: 600px) 400px, 800px"
alt="Description précise"
onLoad={gestionChargement}
onError={gestionErreur}
/>
);
// ❌ Pratique à éviter
const MauvaiseImage = () => (
<Image
src="https://exemple.com/image-non-optimisee.jpg"
alt=""
/>
);