Files
workshop-manager/PERF_OPTIMIZATIONS.md
Froidefond Julien c828ab1a48
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 4m45s
perf: optimize DB queries, SSE polling, and client rendering
- 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>
2026-02-25 14:04:58 +01:00

3.2 KiB
Raw Blame History

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.tsx
  • src/components/moving-motivators/MotivatorCard.tsx (+ MotivatorCardStatic)
  • src/components/weather/WeatherCard.tsx
  • src/components/weekly-checkin/WeeklyCheckInCard.tsx
  • src/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 header X-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/dnd et @dnd-kit en 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