mirror of
https://github.com/MaksTinyWorkshop/_Assistant_Lead_Tech
synced 2026-06-28 01:53:40 +02:00
docs(knowledge): capitalisation frontend — intégration du triage local (mai-juin 2026)
Triage et intégration des propositions frontend du buffer 95_a_capitaliser.md (lot local RL799_V2/Vue3 + app-alexandrie/RN-Expo, mai-juin 2026). ~73 entrées intégrées sur knowledge/frontend/ + 1 nouveau fichier, dont : - patterns/state.md : race-token partagé latest-wins (fusion 3 props), capture sync anti-race, event bus timestamp, clé cache composite, état dérivé = computed - risques/state.md : 9 risques Zustand/store (fetchId reset, useRef remount, re-fetch infini sur [], flag optimiste écrasé, cache détail/liste stale, latch sans reset, :key index) - patterns/navigation.md : Expo Router (tab bar, useFocusEffect, Href typé, routing pur fusionné) - patterns/general.md : helpers temps purs, composants génériques + skeleton, fail-fast, touch target - risques/general.md : 24 risques (sweep statique, filtre client liste paginée, hooks avant return, a11y VoiceOver/disabled, redirection allowlist, RangeError toISOString, section i18n...) - design-tokens (cluster theming light/dark MD3), tests, performance, react-native, nextjs - NOUVEAU risques/responsive.md (gating par capacité d'input + checklist régressions mobile) - READMEs patterns/risques mis à jour Doublons inter-fichiers évités (vérifié : aucune ancre dupliquée introduite). Rejets (doublons 91/9/87), reciblages workflow (156/257) et bloc 32 (CLAUDE projet) non intégrés ici. Source 95_a_capitaliser.md non purgée (purge en fin de capitalisation complète). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -78,3 +78,97 @@ const handleToggle = useCallback((id: string) => { ... }, []); // stable ✓
|
||||
|
||||
- Contexte technique : frontend / mobile — RL799_V2 06-04-2026
|
||||
|
||||
---
|
||||
|
||||
<a id="risque-bundle-spa-non-code-splitte"></a>
|
||||
## Bundle SPA non code-splitté — toute l'app livrée sur la page de login
|
||||
|
||||
### Risques
|
||||
|
||||
- Imports statiques dans le router → tout le code applicatif (modales, panels admin, vues détail, workers PDF) est livré et parsé sur la page de login
|
||||
- DOMContentLoaded de plusieurs dizaines de secondes sur connexion mobile dégradée pour une page à 2 champs ; TTI massif au cold start ; les appareils anciens (CPU lent) paient le parse JS même en wifi
|
||||
- Anti-pattern transverse SPA (Vue Router, React Router, Angular, SvelteKit dev)
|
||||
|
||||
### Symptômes
|
||||
|
||||
- Network DevTools (Slow 4G, cache vidé) sur `/login` : 300+ requêtes JS, 5+ Mo transférés, DOMContentLoaded > 30 s
|
||||
- La waterfall liste des composants d'écrans authentifiés (`Dashboard*`, `Admin*`, modales métier)
|
||||
- Lighthouse mobile : Performance < 50, LCP > 4s, TBT > 1s
|
||||
|
||||
### Signal de détection rapide
|
||||
|
||||
- Network → "Disable cache" + "Preserve log" → Slow 4G → hard reload sur `/login`. Si on voit des composants d'écrans authentifiés dans les requêtes, le code splitting est absent ou cassé.
|
||||
|
||||
### Bonnes pratiques / mitigations
|
||||
|
||||
```ts
|
||||
// ✅ routes en imports dynamiques (Vite + Vue Router natif ; React Router lazy() ; Next auto par page)
|
||||
const routes = [{ path: '/login', component: () => import('@/pages/Login.vue') }];
|
||||
|
||||
// ✅ composants lourds non-critiques en async (modales, viewers PDF)
|
||||
const DocumentPreviewModal = defineAsyncComponent(() => import('@/components/DocumentPreviewModal.vue'));
|
||||
|
||||
// ✅ préchargement post-login : pendant la saisie du mot de passe, pré-charger les chunks suivants
|
||||
import('@/pages/Dashboard.vue'); // dans Login.vue au mount, sans bloquer
|
||||
```
|
||||
|
||||
- Auditer les barrel files (`export * from`) qui empêchent le tree-shaking → préférer `export { specificThing }`
|
||||
- **Mesurer avant/après en Slow 4G + 4× CPU throttling** (sans throttling on mesure son MacBook, pas l'usage réel)
|
||||
- Ordres de grandeur attendus (RL799 estimé) : requêtes login 336 → ~30-50, transfert 6.7 Mo → ~600 ko-1 Mo, DOMContentLoaded 51s → ~5-8s. Risque du fix très faible (mécanique sur le router), coût 2-4 h
|
||||
- Note : sur Next.js le splitting par page est automatique mais ne dispense PAS du `dynamic()` / `defineAsyncComponent` pour les composants lourds
|
||||
- Complète l'entrée "Performances : sur-renders + bundle non maîtrisé" par le signal Network observable et les chiffres
|
||||
- Contexte technique : Vue 3.5 / Vite 7 / Vue Router 4 — RL799_V2 (audit `/login`), 08-05-2026
|
||||
|
||||
---
|
||||
|
||||
<a id="risque-helper-ordre-fige-reverse-caller"></a>
|
||||
## Helper qui n'accepte qu'un ordre → force le caller à `reverse()` (O(n)×2 + clone)
|
||||
|
||||
### Risques
|
||||
|
||||
- Un helper pur qui ne gère que l'ordre ASC force le caller à `helper([...arr].reverse()).reverse()` quand le store sert en DESC (pour `FlatList inverted`)
|
||||
- Coût caché : 2 × O(n) + 1 clone à CHAQUE re-render. Pour un tableau cumulatif (pagination), 500 items × 10 fetchs = 15000+ ops, invisible jusqu'à une conversation longue en prod
|
||||
|
||||
### Symptômes
|
||||
|
||||
- `const result = helper([...store.items].reverse()).reverse();`
|
||||
|
||||
### Bonnes pratiques / mitigations
|
||||
|
||||
```ts
|
||||
// ✅ paramètre order : itère nativement à l'envers, 1 seul reverse final, 0 clone
|
||||
export function helper(items, opts, order: 'asc' | 'desc' = 'asc') {
|
||||
const iterate = order === 'asc'
|
||||
? (cb) => { for (const m of items) cb(m); }
|
||||
: (cb) => { for (let i = items.length - 1; i >= 0; i--) cb(items[i]); };
|
||||
// logique unique basée sur "previousDate", valable dans les deux sens
|
||||
return order === 'desc' ? result.reverse() : result;
|
||||
}
|
||||
```
|
||||
|
||||
- Contexte technique : React Native — app-alexandrie (ux-cleanup-11 H2, `groupMessagesByTime`), 30-05-2026
|
||||
|
||||
---
|
||||
|
||||
<a id="risque-flatlist-renderitem-sans-memo"></a>
|
||||
## Composant `renderItem` de `FlatList` sans `React.memo` → re-render à chaque page
|
||||
|
||||
### Risques
|
||||
|
||||
- `FlatList` virtualise (n'instancie que les items visibles) mais ne mémoïze PAS les props : à chaque update de `data` (fetchNextPage cumulatif), tous les items visibles re-rendent même si leurs props sont inchangées
|
||||
- 100 items visibles → 100 re-renders inutiles à chaque page chargée
|
||||
|
||||
### Symptômes
|
||||
|
||||
- Lag au scroll / au chargement de page sur une liste longue (DM, notif, contenu)
|
||||
|
||||
### Bonnes pratiques / mitigations
|
||||
|
||||
```tsx
|
||||
export const MessageBubble = React.memo(function MessageBubble(props) { /* … */ });
|
||||
```
|
||||
|
||||
- Tout composant rendu dans un `FlatList renderItem` doit être enveloppé dans `React.memo` (audit : grep `<FlatList renderItem`)
|
||||
- Si les handlers changent à chaque render parent : les mémoïser (`useCallback`) ou accepter le re-render. Comparateur custom rarement nécessaire si les props sont stables côté store
|
||||
- Contexte technique : React Native — app-alexandrie (ux-cleanup-11 M4/M5), 29-05-2026
|
||||
|
||||
|
||||
Reference in New Issue
Block a user