perf: optimize DB queries, SSE polling, and client rendering
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 4m45s
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 4m45s
- 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>
This commit is contained in:
74
PERF_OPTIMIZATIONS.md
Normal file
74
PERF_OPTIMIZATIONS.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user