- Fix resolveCollaborator N+1: replace full User table scan with findFirst - Fix getAllUsersWithStats N+1: use groupBy instead of per-user count queries - Cache getTeamMemberIdsForAdminTeams and isAdminOfUser with React.cache - Increase SSE poll interval from 1s to 2s across all 5 subscribe routes - Add cleanupOldEvents method to session-share-events for event table TTL - Add React.memo to all card components (Swot, Motivator, Weather, WeeklyCheckIn, YearReview) - Fix WeatherCard useEffect+setState lint error with idiomatic prop sync pattern - Add optimizePackageImports for DnD libs and poweredByHeader:false in next.config - Add inline theme script in layout.tsx to prevent dark mode FOUC - Remove unused Next.js template SVGs from public/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3.2 KiB
Optimisations de performance
Requêtes DB (impact critique)
resolveCollaborator — suppression du scan complet de la table User
Fichier: src/services/auth.ts
Avant : findMany sur tous les users puis find() en JS pour un match case-insensitive par nom.
Après : findFirst avec contains + vérification exacte. O(1) au lieu de O(N users).
getAllUsersWithStats — suppression du N+1
Fichier: src/services/auth.ts
Avant : 2 queries count par utilisateur (Promise.all avec map).
Après : 2 groupBy en bulk + construction d'une Map. 3 queries au lieu de 2N+1.
React.cache sur les fonctions teams
Fichier: src/services/teams.ts
getTeamMemberIdsForAdminTeams et isAdminOfUser wrappées avec React.cache().
Sur la page /sessions, ces fonctions étaient appelées ~10 fois par requête (5 workshop types × 2). Maintenant dédupliquées en 1 appel.
SSE / Temps réel (impact haut)
Polling interval 1s → 2s
Fichiers: 5 routes src/app/api/*/[id]/subscribe/route.ts
Réduit de 50% le nombre de queries DB en temps réel. Imperceptible côté UX (la plupart des outils collab utilisent 2-5s).
Nettoyage des events
Fichier: src/services/session-share-events.ts
Ajout de cleanupOldEvents(maxAgeHours) pour purger les events périmés. Les tables d'events n'ont pas de mécanisme de TTL — cette méthode peut être appelée périodiquement ou à la connexion SSE.
Rendu client (impact haut)
React.memo sur les composants de cartes
Fichiers:
src/components/swot/SwotCard.tsxsrc/components/moving-motivators/MotivatorCard.tsx(+MotivatorCardStatic)src/components/weather/WeatherCard.tsxsrc/components/weekly-checkin/WeeklyCheckInCard.tsxsrc/components/year-review/YearReviewCard.tsx
Ces composants sont rendus en liste et re-rendaient tous à chaque drag, changement d'état, ou router.refresh() SSE.
WeatherCard — fix du pattern useEffect + setState
Fichier: src/components/weather/WeatherCard.tsx
Remplacé le useEffect qui appelait 5 setState (cascading renders, erreur lint React 19) par le pattern idiomatique de state-driven prop sync (comparaison directe dans le render body).
Configuration Next.js (impact moyen)
next.config.ts
Fichier: next.config.ts
poweredByHeader: false— supprime le headerX-Powered-By(sécurité)optimizePackageImports— tree-shaking amélioré pour@dnd-kit/*et@hello-pangea/dnd
Fix FOUC dark mode
Fichier: src/app/layout.tsx
Script inline dans <head> qui lit localStorage et applique la classe dark/light sur <html> avant l'hydratation React. Élimine le flash blanc pour les utilisateurs en dark mode.
Nettoyage
- Suppression de 5 SVGs inutilisés du template Next.js (
file.svg,globe.svg,next.svg,vercel.svg,window.svg)
Non traité (pour plus tard)
- Migration DnD : consolider
@hello-pangea/dndet@dnd-kiten une seule lib (~45KB économisés) — 3 boards à réécrire - Split WorkshopTabs (879 lignes) — découper en sous-composants par type
- Suspense boundaries sur les pages de détail de session
- Appel périodique de
cleanupOldEvents— à brancher via cron ou à la connexion SSE