PHASE G — PERFORMANCE
G1. Bundle
Build status
- 🔴 Le build échoue actuellement — import manquant
educationService dans useEducationView.ts
- Analyse basée sur le dernier build réussi dans
dist_verification/
Taille du build (dernier build disponible)
| Catégorie |
Taille |
Verdict |
| Total dist/ |
6.8 MB |
⚠️ Élevé (includes mockServiceWorker) |
| JS total |
~1.4 MB |
⚠️ Significatif |
| CSS total |
~150 KB |
✅ Raisonnable |
Chunks JS (triés par taille)
| Chunk |
Taille |
Contenu |
vendor-*.js |
925 KB |
Dépendances générales (axios, zustand, framer-motion, etc.) |
index-*.js |
113 KB |
Code applicatif principal |
vendor-react-*.js |
85 KB |
React + React DOM |
vendor-utils-*.js |
37 KB |
date-fns, zod |
routes-*.js |
33 KB |
Route definitions |
vendor-tanstack-*.js |
21 KB |
TanStack React Query |
TrackDetailPage-*.js |
21 KB |
Page lazy-loaded |
vendor-icons-*.js |
17 KB |
Lucide icons |
SettingsPage-*.js |
17 KB |
Page lazy-loaded |
ChatPage-*.js |
17 KB |
Page lazy-loaded |
Problèmes identifiés
| Problème |
Impact |
Fichier |
vendor-*.js à 925 KB |
🔴 Chunk vendor monolithique trop gros |
vite.config.ts:85-98 |
mockServiceWorker.js dans le build |
⚠️ 13 KB de MSW en production |
Build output |
swagger-ui-react en production deps |
⚠️ Potentiellement inclus dans vendor |
package.json |
rollup-plugin-visualizer en production deps |
⚠️ Devrait être en devDependencies |
package.json |
Tree-shaking
- ✅ Imports nommés pour
lucide-react (vendor-icons à 17 KB — excellent pour ~50 icônes)
- ✅ Manual chunks configurés pour React, Router, TanStack, icons, utils
- ⚠️ Le chunk
vendor de 925 KB suggère un tree-shaking incomplet des dépendances principales
- ⚠️
emoji-picker-react (~200 KB), framer-motion (~30 KB), hls.js (~50 KB) probablement dans vendor
Source maps
- ✅
sourcemap: 'hidden' en production — source maps générées mais non exposées publiquement
G2. Code splitting
React.lazy()
| Fichier |
Composant lazy |
Usage |
components/ui/lazy-component/createLazyComponent.tsx:48 |
Route components |
✅ Toutes les routes |
features/chat/components/ChatMessage.tsx:11 |
EmojiPicker |
✅ Composant lourd |
features/chat/components/ChatInput.tsx:31 |
EmojiPicker |
✅ Composant lourd |
components/ui/ImageCropper.tsx:4 |
Cropper |
✅ Composant lourd |
components/feedback/LazyToaster.tsx:15 |
Toaster |
✅ Non-critique |
Routes lazy-loadées
- ✅ 100% des routes sont lazy-loaded via
createLazyComponent
- ✅ Chaque page a son propre chunk (TrackDetailPage-.js, ChatPage-.js, etc.)
Composants lourds
| Composant |
Lazy-loaded ? |
Taille estimée |
| EmojiPicker |
✅ Oui |
~200 KB |
| ImageCropper |
✅ Oui |
~50 KB |
| SwaggerUI |
❌ Non |
~2 MB potentiel |
| Charts |
❌ Non |
Variable |
| WaveformVisualizer |
❌ Non |
~20 KB |
Problème : swagger-ui-react n'est PAS lazy-loaded — s'il est importé dans un composant non-lazy, il pourrait gonfler le bundle principal.
G3. Optimisation du rendu
Memoization
| Hook |
Instances |
Verdict |
useMemo |
~50+ |
✅ Bien utilisé (filtered lists, expensive computations) |
useCallback |
~80+ |
✅ Bien utilisé (event handlers, child callbacks) |
React.memo |
5 |
⚠️ Sous-utilisé (TrackCard, PlaylistCard, CourseCard, ProductCard, PostCard) |
React.memo manquant :
- Les composants de liste (
TrackGrid, PlaylistList) bénéficieraient de React.memo sur les items
- Les items des menus de navigation pourraient être memoizés
useEffect
| Métrique |
Valeur |
| Total useEffect |
~200+ instances |
| Fichiers avec 5+ useEffect |
2-3 (App.tsx, usePlayer.ts) |
⚠️ App.tsx avec 6+ useEffect est un signal de surcharge — devrait être décomposé.
Context providers trop larges
- ⚠️
AuthContext et ThemeContext wrappent toute l'application — tout changement d'état provoque un re-render de l'arbre entier
- ✅ Zustand stores avec selectors ne causent pas de re-renders en cascade
- ✅ React Query cache est indépendant du rendu
Listes sans key ou avec key={index}
- ⚠️ 100+ instances de
key={index} ou key={i}
- La plupart sont des skeletons et listes statiques — acceptable
- ⚠️ Certaines listes dynamiques (dashboard, chat messages) pourraient utiliser des IDs stables
G4. Assets
Images
- ❌ Aucun
loading="lazy" détecté sur les <img>
- ✅ Composant
OptimizedImage avec blur placeholder et fallback
- ⚠️ Pas de WebP/AVIF automatique (pas de pipeline d'optimisation d'images détecté)
- ⚠️ Pas de
srcset ou sizes pour les images responsives
Fonts
- ⚠️ Pas de
@font-face déclarations — fonts chargées via Google Fonts (externe)
- ⚠️ Pas de
font-display: swap explicite dans le CSS (dépend du chargement Google Fonts)
- ⚠️ Pas de
<link rel="preload"> pour les fonts
- Fonts utilisées : Barlow, Inter, Noto Sans JP, JetBrains Mono, Orbitron, Source Serif 4 — 6 familles de polices est excessif
SVG
- ✅ 5 fichiers SVG — faible impact
- ✅ Pas de SVG inlinés massifs détectés
G5. Requêtes réseau
Waterfall
- ✅ React Query avec
staleTime: 1min évite les requêtes redondantes
- ✅ Request deduplication dans le client API
- ⚠️ Pas de prefetching détecté (pas de
queryClient.prefetchQuery)
- ⚠️ Routes lazy-loaded + données = double waterfall (JS chunk + API call)
Cache HTTP
- ✅ Response caching côté client dans le API client
- ✅ React Query gcTime de 5 minutes
- [DONNÉES INSUFFISANTES — headers Cache-Control côté serveur non analysés]
WebSocket
- ✅ Reconnection automatique avec exponential backoff
- ✅ Max 5 tentatives de reconnection
- ⚠️ Pas de heartbeat/ping explicite détecté dans
websocket.ts
SCORE PERFORMANCE : 6/10
Points gagnés
| Point |
Score |
Justification |
| 100% routes lazy-loaded |
+1.5 |
Excellent code splitting au niveau route |
| Manual chunks Vite |
+0.8 |
React, router, tanstack, icons séparés |
| React Query cache |
+0.8 |
staleTime, gcTime, deduplication |
| Memoization hooks |
+0.7 |
useMemo/useCallback bien utilisés |
| Composants lourds lazy |
+0.5 |
EmojiPicker, ImageCropper |
| Source maps hidden |
+0.3 |
Pas exposés en production |
| Virtualization |
+0.4 |
TanStack Virtual pour les listes longues |
Points perdus
| Point |
Score |
Justification |
| Build cassé |
-1.0 |
Impossible de déployer |
| Vendor chunk 925 KB |
-0.8 |
Chunk monolithique trop gros |
| Pas de loading="lazy" images |
-0.5 |
Toutes les images chargées eagerly |
| 6 familles de fonts |
-0.5 |
Impact LCP et FOIT/FOUT |
| SwaggerUI non lazy |
-0.3 |
Potentiel 2 MB dans le bundle |
| React.memo sous-utilisé |
-0.3 |
5 instances seulement |
| Pas de prefetching |
-0.3 |
Double waterfall routes + données |
| Pas de font preload |
-0.2 |
Blocage de rendu potentiel |
| key={index} fréquent |
-0.1 |
Minor mais présent |