- Updated CodeRendererComponent to use Angular's new input() signals instead of @Input decorators - Added fallback content escaping for code that can't be syntax highlighted - Improved code viewer styling with larger fonts, better padding and gradient header background - Enhanced file content fetching with robust cache-busting and fallback mechanisms - Added debug logging to track content loading and syntax highlighting - Fixe
261 lines
12 KiB
Markdown
261 lines
12 KiB
Markdown
# ObsiViewer Nimbus — Performance Roadmap & Todo List (Angular 20 + Tailwind 3.4)
|
||
|
||
Cette roadmap est une liste d’actions priorisées pour optimiser les performances côté client de l’interface Nimbus, en respectant strictement:
|
||
|
||
- Angular 20 (signals, @for/@if, @defer, standalone, zoneless)
|
||
- TailwindCSS 3.4 (purge actuelle conservée)
|
||
- UI/UX Nimbus existante (aucun changement visuel ou de comportement attendu)
|
||
- Modes Desktop et Mobile
|
||
|
||
Chaque tâche contient: Objectif mesurable, Critères d’acceptation, Emplacements de code, Risques/Dépendances et un Prompt prêt à l’emploi pour exécuter la tâche à 100% (desktop + mobile).
|
||
|
||
---
|
||
|
||
## ✅ Phase 0 — Quick Wins (ROI élevé, faible risque)
|
||
|
||
### 0.1 Retirer l’import global Excalidraw du bundle initial
|
||
- Objectif: réduire la taille du bundle initial et le TTI en excluant `@excalidraw/excalidraw` du chunk principal.
|
||
- Critères d’acceptation:
|
||
- L’import global n’apparaît plus dans `index.tsx`.
|
||
- Le Drawings Editor reste fonctionnel via import dynamique (`web-components/excalidraw/define`).
|
||
- Build prod montre une baisse du poids du bundle initial (source-map-explorer).
|
||
- Emplacements: `index.tsx`, `src/app/features/drawings/drawings-editor.component.ts`, `web-components/excalidraw/define.ts`.
|
||
- Risques/Dépendances: s’assurer que les usages Excalidraw restent lazy et conditionnels.
|
||
- Prompt:
|
||
```
|
||
Tu es un pair-programmer Angular 20. Objectif: retirer tout import global d'Excalidraw du bundle initial sans casser le Drawings Editor. Étapes:
|
||
1) Ouvre `index.tsx` et supprime toute ligne `import '@excalidraw/excalidraw'`.
|
||
2) Vérifie que `src/app/features/drawings/drawings-editor.component.ts` importe `../../../../web-components/excalidraw/define` via `await import(...)`.
|
||
3) Lance un build prod avec stats et analyse les bundles (source-map-explorer) pour confirmer la réduction du main chunk.
|
||
4) Teste Desktop et Mobile: ouverture d’un fichier .excalidraw.md dans l’éditeur (réactivité, chargement lazy OK).
|
||
5) Ne change pas l’UI/UX. Respecte Angular 20 et Tailwind 3.4.
|
||
```
|
||
|
||
### ✅ 0.2 Virtualiser la liste centrale Nimbus avec `PaginatedNotesList`
|
||
|
||
- Objectif: maintenir ≥55 FPS et mémoire <200MB avec 5k+ notes.
|
||
- Critères d’acceptation:
|
||
- Le centre affiche `PaginatedNotesListComponent` (CDK virtual scroll + pagination).
|
||
- Scroll fluide Desktop/Mobile, FPS ≥55 sur 5k items.
|
||
- Émissions/inputs existants (openNote, queryChange, selectedId, quickLink) préservés.
|
||
- Emplacements: `src/app/layout/app-shell-nimbus/app-shell-nimbus.component.ts` (zones de liste Desktop/Tablet/Mobile).
|
||
- Risques/Dépendances: compatibilité filtres/search/URL state; conserver événements.
|
||
- Prompt:
|
||
```
|
||
Tu es un expert Angular 20/CDK Virtual Scroll. Remplace la liste centrale dans `AppShellNimbus` par `PaginatedNotesListComponent` sans changer l’UX.
|
||
1) Identifie les trois zones de rendu de la liste (desktop/tablet/mobile) dans `app-shell-nimbus.component.ts`.
|
||
2) Remplace le composant de liste actuel par `<app-paginated-notes-list>` en câblant:
|
||
- Inputs: folderFilter, tagFilter, quickLinkFilter, query, selectedId
|
||
- Outputs: openNote, queryChange, clearQuickLinkFilter
|
||
3) Vérifie Desktop/Mobile: scroll fluide, sélection, recherche, quick links.
|
||
4) Mesure FPS (DevTools) sur 5k notes; objectif ≥55 FPS.
|
||
5) Pas de modification visuelle. Respecte Angular 20/Tailwind 3.4.
|
||
```
|
||
|
||
### 0.3 Déférer les viewers lourds (PDF/Video/Excalidraw/Code) via `@defer`
|
||
|
||
- Objectif: réduire LCP et TTI en chargeant à la demande les viewers lourds.
|
||
- Critères d’acceptation:
|
||
- `@defer` entourant le SmartFileViewer (non-markdown) avec placeholder.
|
||
- Le chunk viewer se charge uniquement quand visible (on viewport/interactions).
|
||
- Pas de régression Desktop/Mobile.
|
||
- Emplacements: `src/components/tags-view/note-viewer/note-viewer.component.ts` (ou template), `src/components/smart-file-viewer/`.
|
||
- Risques/Dépendances: placeholders légers; événements image/video conservés.
|
||
- Prompt:
|
||
```
|
||
Tu es un spécialiste Angular 20. Déferre l’affichage des viewers lourds.
|
||
1) Dans le template NoteViewer (ou SmartFileViewer), entoure le rendu non-markdown avec `@defer (on viewport)` et un placeholder léger.
|
||
2) Garde le rendu markdown immédiat.
|
||
3) Vérifie Desktop/Mobile: ouverture d’un PDF/Excalidraw/Video/Code charge un chunk async seulement à l’affichage.
|
||
4) Mesure LCP/TTI avant/après (Lighthouse Mobile). Objectif: LCP ≤ 2.5s, TTI ≤ 3.0s.
|
||
5) Aucun changement d’UI. Respecte Angular 20/Tailwind 3.4.
|
||
```
|
||
|
||
### 0.4 Adopter `NgOptimizedImage` pour les images
|
||
|
||
- Objectif: améliorer LCP et éliminer CLS en fournissant dimensions/sizes.
|
||
- Critères d’acceptation:
|
||
- `NgOptimizedImage` importé et `ngSrc` utilisé dans `image-viewer`.
|
||
- Dimensions (width/height) ou stratégie calculée, `sizes` renseigné.
|
||
- LCP image ↓ et CLS ≈ 0.
|
||
- Emplacements: `src/app/features/note-view/components/image-viewer/image-viewer.component.ts` (+ contenu markdown rendu si applicable).
|
||
- Risques/Dépendances: fournir dimensions raisonnables; ne pas dégrader mise en page.
|
||
- Prompt:
|
||
```
|
||
Tu es un dev Angular 20. Optimise les images avec NgOptimizedImage.
|
||
1) Dans `image-viewer.component.ts`, ajoute `NgOptimizedImage` aux imports standalone.
|
||
2) Remplace `src` par `ngSrc` et fournis `width`, `height`, `sizes`.
|
||
3) Vérifie Desktop/Mobile: absence de sauts de layout (CLS), affichage net, LCP image améliorée.
|
||
4) Garde les événements/émissions inchangés. Pas de changement visuel.
|
||
```
|
||
|
||
### 0.5 Convertir les `*ngFor` restants en `@for` avec `track`
|
||
|
||
- Objectif: réduire le coût de diffing et stabiliser l’identité des items.
|
||
- Critères d’acceptation:
|
||
- Listes dynamiques dans Nimbus utilisent `@for (...; track ...)`.
|
||
- Aucune régression d’interaction (sélection tags/dossiers/etc.).
|
||
- Emplacements: `app-shell-nimbus.component.ts` (ex. flyout tags/dossiers) et autres listes restantes.
|
||
- Risques/Dépendances: choisir une clé stable (`id`, `name`).
|
||
- Prompt:
|
||
```
|
||
Tu es un expert Angular 20. Modernise les boucles.
|
||
1) Recherc he `*ngFor` dans les templates Nimbus et remplace-les par `@for`.
|
||
2) Ajoute un `track` stable (id, name) pour chaque liste.
|
||
3) Teste Desktop/Mobile: navigation, clics tags/dossiers, pas de re-rendu excessif.
|
||
```
|
||
|
||
---
|
||
|
||
## Phase 1 — Correctifs cœur
|
||
|
||
### 1.1 Throttling/Debouncing des entrées + écouteurs passifs
|
||
|
||
- Objectif: TBT ≤ 150ms, INP ≤ 200ms durant saisie/recherche/scroll.
|
||
- Critères d’acceptation:
|
||
- Flux de recherche: debounce/throttle ~16–100ms.
|
||
- Écouteurs scroll/wheel/resize en `{ passive: true }` si custom.
|
||
- Profiler: long tasks ↓ et input latency ↓ sur Desktop/Mobile.
|
||
- Emplacements: composants de recherche/liste; directives éventuelles d’événements.
|
||
- Prompt:
|
||
```
|
||
Tu es un dev perf Angular. Lisse les entrées.
|
||
1) Ajoute debounce/throttle (RxJS) aux flux de recherche et scroll.
|
||
2) Convertis tout `addEventListener` custom en `{ passive: true }` si pertinent.
|
||
3) Mesure INP/TBT (Lighthouse Mobile). Objectifs: INP ≤ 200ms, TBT ≤ 150ms.
|
||
```
|
||
|
||
### 1.2 Déférer panneaux lourds (paramètres/tests/about)
|
||
|
||
- Objectif: réduire bundle initial et coût de rendu.
|
||
- Critères d’acceptation:
|
||
- Panneaux secondaires rendus via `@defer (on interaction)` + placeholder.
|
||
- Aucun changement d’UX; charge uniquement à l’ouverture.
|
||
- Emplacements: `app-shell-nimbus.component.ts` (panneaux/overlays non essentiels).
|
||
- Prompt:
|
||
```
|
||
Tu es un expert Angular 20. Déferre les panneaux non essentiels.
|
||
1) Ajoute `@defer (on interaction)` autour des panneaux paramètres/tests/about.
|
||
2) Placeholder léger et accessibilité préservée.
|
||
3) Vérifie Desktop/Mobile: ouverture fluide, chunks chargés à la demande.
|
||
```
|
||
|
||
### 1.3 Vérifier import conditionnel des libs lourdes
|
||
|
||
- Objectif: `@excalidraw/excalidraw`, PDF et autres libs uniquement chargés si viewer requis.
|
||
- Critères d’acceptation: aucun import global résiduel; lazy import confirmé (network waterfall).
|
||
- Emplacements: `smart-file-viewer`, `drawings-editor`, pdf viewer.
|
||
- Prompt:
|
||
```
|
||
Tu es un dev Angular. Vérifie et force les imports conditionnels.
|
||
1) Inspecte smart-file-viewer/drawings-editor/pdf-viewer: pas d’import global.
|
||
2) Les imports doivent être dynamiques/conditionnels à l’usage.
|
||
3) Confirme au profiler: chunks chargés seulement si nécessaires.
|
||
```
|
||
|
||
---
|
||
|
||
## Phase 2 — Refactors profonds
|
||
|
||
### 2.1 Slices de store par signals (Sélection/Filtre/Recherche)
|
||
|
||
- Objectif: diminuer les re-rendus et effets transverses.
|
||
- Critères d’acceptation:
|
||
- Séparation claire des signals; reactivité localisée; pas de boucle.
|
||
- UX identique; URL state toujours synchronisé.
|
||
- Emplacements: `AppComponent`, `AppShellNimbusLayoutComponent`, services d’état/URL.
|
||
- Prompt:
|
||
```
|
||
Tu es un architecte Angular 20. Isoles les états en slices par signals.
|
||
1) Identifie les states très utilisés (sélection, filtres, recherche).
|
||
2) Crée des slices/cohorts de signals avec computed/effects.
|
||
3) Assure la synchro URL <-> UI intacte. Tests Desktop/Mobile.
|
||
```
|
||
|
||
### 2.2 content-visibility/contain pour grands conteneurs
|
||
|
||
- Objectif: réduire le coût de layout/paint hors écran.
|
||
- Critères d’acceptation: scrolling et navigation plus fluides; aucune régression visuelle.
|
||
- Emplacements: grands conteneurs de liste/notes (CSS global ou scss locaux).
|
||
- Prompt:
|
||
```
|
||
Tu es un expert CSS perf. Ajoute `content-visibility: auto` et `contain-intrinsic-size` sur les grands conteneurs offscreen.
|
||
1) Cible les conteneurs principaux liste/viewer.
|
||
2) Vérifie Desktop/Mobile: aucun artefact; paint/layout réduits (Performance panel).
|
||
```
|
||
|
||
### 2.3 Pipeline images responsive (thumb→medium→full)
|
||
|
||
- Objectif: améliorer le temps de rendu perçu des assets visuels.
|
||
- Critères d’acceptation: affichage progressif sans saut, qualité finale correcte.
|
||
- Emplacements: chargement d’images (viewer et markdown rendu).
|
||
- Prompt:
|
||
```
|
||
Tu es un dev front. Mets en place un pipeline responsive images.
|
||
1) Servez d’abord une miniature, puis une image medium, puis la full.
|
||
2) Adapte `sizes/srcset` (NgOptimizedImage) pour Desktop/Mobile.
|
||
3) Mesure LCP perçu et absence de CLS.
|
||
```
|
||
|
||
---
|
||
|
||
## Phase 3 — Plateforme / Build
|
||
|
||
### 3.1 Budgets Angular (initial, anyComponentStyle, css)
|
||
|
||
- Objectif: prévenir les régressions de poids.
|
||
- Critères d’acceptation: budgets ajoutés à `angular.json`; build échoue si dépassement.
|
||
- Emplacements: `angular.json`.
|
||
- Prompt:
|
||
```
|
||
Tu es un mainteneur Angular. Ajoute des budgets stricts.
|
||
1) Ajoute budgets pour initial (warn 1400kb / error 1800kb), anyComponentStyle, css.
|
||
2) Lance un build prod pour valider.
|
||
3) Documente dans README/CI les seuils.
|
||
```
|
||
|
||
### 3.2 Scripts d’analyse + (optionnel) Lighthouse CI gate
|
||
- [] done
|
||
|
||
- Objectif: visibilité continue et garde-fous automatiques.
|
||
- Critères d’acceptation: scripts npm `build:stats` et `analyze:bundle`; pipeline peut exécuter Lighthouse avec seuils mobiles.
|
||
- Emplacements: `package.json`, CI.
|
||
- Prompt:
|
||
```
|
||
Tu es un dev outillage. Ajoute scripts d’analyse et un job Lighthouse CI (optionnel).
|
||
1) `build:stats` (ng build --stats-json) et `analyze:bundle` (source-map-explorer) dans package.json.
|
||
2) Pipeline: exécute Lighthouse Mobile/Desktop et échoue si LCP/TTI/CLS/TBT hors seuils.
|
||
3) Ne modifie pas le code applicatif.
|
||
```
|
||
|
||
---
|
||
|
||
## Mesure & Validation
|
||
|
||
- Baseline puis post-implémentation: Lighthouse Mobile (4x CPU, 1.5 Mbps) et Desktop.
|
||
- Objectifs cibles:
|
||
- LCP ≤ 2.5s (Mobile), TTI ≤ 3.0s, CLS ≤ 0.02, TBT ≤ 150ms
|
||
- Liste 5k items: ≥55 FPS, mémoire <200MB
|
||
- Bundle initial: -40% vs baseline si possible
|
||
- Scripts utiles:
|
||
- `npm run build:stats`
|
||
- `npx source-map-explorer "dist/**/*.js"`
|
||
|
||
---
|
||
|
||
## Checklist globale (progression)
|
||
|
||
- [x] 0.1 Retirer import global Excalidraw
|
||
- [ ] 0.2 Virtualiser liste centrale Nimbus (PaginatedNotesList)
|
||
- [ ] 0.3 Déférer viewers lourds (@defer)
|
||
- [ ] 0.4 NgOptimizedImage pour images
|
||
- [ ] 0.5 Convertir *ngFor → @for avec track
|
||
- [ ] 1.1 Throttle/Debounce + passive listeners
|
||
- [ ] 1.2 Déférer panneaux non essentiels
|
||
- [ ] 1.3 Imports conditionnels libs lourdes
|
||
- [ ] 2.1 Slices signals (Sélection/Filtre/Recherche)
|
||
- [ ] 2.2 content-visibility/contain pour conteneurs
|
||
- [ ] 2.3 Pipeline images responsive
|
||
- [ ] 3.1 Budgets Angular
|
||
- [ ] 3.2 Scripts analyse + Lighthouse CI (opt.)
|