- Added comprehensive filtering system with support for file types, tags, and quick links - Implemented sort options (title, created, updated) with dropdown menu - Added three view modes (compact, comfortable, detailed) for different density layouts - Added note color indicators and hover actions (edit, delete) to note cards - Integrated file type detection with appropriate icons for different content types - Added filter badges to show
12 KiB
12 KiB
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/excalidrawdu 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).
- L’import global n’apparaît plus dans
- 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.
- Le centre affiche
- 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:
@deferentourant 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:
NgOptimizedImageimporté etngSrcutilisé dansimage-viewer.- Dimensions (width/height) ou stratégie calculée,
sizesrenseigné. - 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.).
- Listes dynamiques dans Nimbus utilisent
- 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.
- Panneaux secondaires rendus via
- 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:statsetanalyze: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:statsnpx source-map-explorer "dist/**/*.js"
Checklist globale (progression)
- 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.)