Nodefony 10.0.0-beta.5
Framework Node.js fullstack — HTTP & WebSocket, même contexte

Barre de débogage — nodefony/debugbar

stablenodefony (cœur)mis à jour 2026-10-24

Une bande fine en bas de page, en développement, qui montre ce que le serveur est en train de faire : le débit temps réel, la charge, la mémoire, les requêtes réseau et les journaux — sans quitter l’écran qu’on est en train de construire.

Elle est livrée avec le cœur et ne dépend d’aucun cadre front : elle s’installe dans une page rendue par un serveur comme dans une application React, Vue, Angular ou Svelte.

📍 Documentation › nodefony — le cœur › Barre de débogage

Démarrage rapide#

/// <reference types="vite/client" />
// Dans un front servi par Vite : `import.meta.env.DEV` vaut true en développement.
import { mountDebugBar } from "nodefony/debugbar";

// En développement uniquement — la barre n'a rien à faire en production.
if (import.meta.env.DEV) mountDebugBar();

Sur une page rendue par le serveur, sans étape de construction :

<script
  type="module"
  src="/node_modules/nodefony/dist/client/debugbar.standalone.js"
></script>

La barre lit le canal temps réel de l’application. Elle n’ouvre aucune seconde connexion : elle partage la socket déjà présente si la page en a une. Et elle ne l’ouvre pas au montage : la socket appartient à l’application, qui décide quand l’ouvrir (la console d’administration attend le login). La barre ne se connecte que quand on lui demande des données — panneau ouvert, ou temps réel démarré.

Ce qu’on voit, et ce qu’on peut faire#

Le bandeau porte l’essentiel en une ligne : le logo, l’environnement du serveur (connu dès le rendu de la page), la branche git (une fois connue), le contrôle « Temps réel », puis le débit, la charge processeur et la mémoire, enfin les compteurs réseau, rechargements à chaud (hmr, avec un front Vite), journaux et erreurs. Ce qui n’est pas encore connu ne s’affiche pas : un badge vide se lirait comme une valeur.

Chaque élément du bandeau porte une aide qui s’ouvre au survol et au focus clavier, et chaque indicateur est un raccourci : cliquer « cpu » ouvre l’onglet qui le détaille. Le bandeau lui-même ne se replie pas au clic : seuls le logo et le bouton « Ouvrir / Fermer » basculent le panneau.

Contrôle Ce qu’il fait
logo ◆ nodefony Ouvre ou ferme le panneau.
Temps réel · <état> Démarre ou arrête les mesures et journaux en direct. Arrêté par défaut (voir ci-dessous).
Réduire Réduit la barre en pastille, dans un coin de l’écran ; la pastille la rouvre.
Ouvrir / Fermer Ouvre ou ferme le panneau.
réglages : À gauche/droite Coin où se pose la pastille réduite (onglet Runtime, carte « Stockage local »).

Le contrôle « Temps réel » dit son état en toutes lettres : arrêté, connexion…, en direct, en pause (la socket est ouverte par l’application, mais la barre ne reçoit rien), ou accès refusé — la barre lit les données d’administration, et sans session administrateur le serveur refuse le handshake (401/403, avant toute ouverture). Le refus se lit, il ne se confond pas avec une panne.

Pourquoi le temps réel est arrêté par défaut : l’abonnement fait tourner des compteurs et un émetteur de journaux côté serveur. En développement on ouvre beaucoup d’onglets ; les laisser tous branchés en permanence ferait payer à l’application un travail que personne ne regarde. C’est un choix d’adhésion, pas une option cachée.

Les cinq onglets#

Realtime — débit, transport, protocole, état de la socket, frames reçues, pic. C’est la vue de la socket elle-même.

Requêtes — les requêtes de la page (fetch et XHR), chacune avec les lignes que le serveur a écrites pour elle, et les autres journaux du serveur en direct. Voir la section suivante.

Perf — processeur, mémoire, boucle d’événements du serveur.

Nodefony client — ce que Nodefony fait dans le navigateur, quand la page compose un noyau client (NodefonyKernel). Quatre cartes, chacune répond à une question :

Chaque libellé porte une explication courte, au survol comme au clavier. Une puce « client · prêt » apparaît dans la bande dès qu’un noyau est détecté — qu’il soit né avant ou après la barre. Sans noyau, l’onglet dit comment en créer un. Le noyau publie cette sonde en développement seulement : en production, rien n’est posé sur la page.

Runtime — l’identité du processus servi (version, environnement, pid, disponibilité, cœurs, mémoire), et ce que la barre garde sur ce navigateur.

L’onglet Requêtes#

Trois vues, au choix en haut de l’onglet :

WebSocket et flux d’événements#

La vue Page montre aussi les connexions longues que la page ouvre : une WebSocket (WS), un EventSource ou un fetch qui reçoit text/event-stream (SSE, ce que fait le client NodefonySse). La socket que la page partage avec la barre y figure comme les autres.

Ce que la ligne montre, c’est ce que seul le navigateur sait : la connexion en cours, l’ouverture (101, 200), la fermeture et son code (1000 normale, 1006 coupée, en rouge), un refus avant l’ouverture, les reconnexions d’un EventSource. La colonne durée dit « ouvert » tant que la connexion vit, puis sa durée de vie. Aucune trame n’est lue ni comptée, binaire compris : ce que la socket transporte reste à l’application.

Choisie, une socket retrouve son requestId par sa ligne d’accès dans les journaux, car le navigateur ne lit pas ses en-têtes. Elle se déplie alors sur ses lignes serveur. Le volet liste les appels passés par la socket, c’est-à-dire chaque api.request. Une connexion n’a pas de profil à elle, puisqu’elle ne se termine qu’à sa fermeture, mais chacun de ses appels en a un. Un clic sur un appel affiche ses phases et ses requêtes SQL, comme pour une requête HTTP. Sur une page de la console, choisir la socket ouvre aussi son Suivi de requête, qui reconstitue tout son cycle.

Un flux SSE n’écrit sa ligne d’accès qu’à sa fermeture : son requestId ne se lit qu’alors, sauf s’il passe par fetch, qui lit ses en-têtes dès l’ouverture. Un flux reçu par fetch se sait fermé par son signal d’abandon : sans signal, la ligne reste « ouvert ».

Un clic ouvre le détail dans un seul volet, à côté : pour une requête, ce qui en a été vu, puis son profil serveur (route, contrôleur, utilisateur, chronologie des phases, requêtes SQL) ; pour une ligne, son horodatage complet, sa catégorie, son worker et sa requête — de quoi coller une trace dans un ticket. Le volet s’ouvre à côté plutôt que dans la liste, qui ne bouge donc pas.

La plus récente est en haut, visible sans défiler. Tant que la liste est tout en haut, elle suit le flux. Dès qu’on descend lire, elle se fige : ni les nouvelles qui arrivent au-dessus, ni les anciennes qui partent en dessous, ni une requête qu’on déplie ne déplacent la ligne qu’on lit, et un bouton « ↑ N nouvelles » ramène au flux (Début au clavier fait de même).

La barre d’outils permet de :

Sans interception réseau (network: false), l’onglet ne montre que les lignes du serveur : c’est la seule partie de la barre qui instrumente des fonctions globales du navigateur.

Ce que l’onglet coûte à l’application#

Ce que la barre garde sur votre navigateur#

Sept valeurs, uniquement d’apparence, dans le stockage local — visibles dans l’onglet Runtime, avec un bouton pour les effacer :

Clé Ce qu’elle retient
nf.debugbar.v version du format ci-dessous
nf.debugbar.visible barre affichée ou masquée
nf.debugbar.min réduite en pastille
nf.debugbar.side côté du dock
nf.debugbar.tab dernier onglet ouvert
nf.debugbar.h hauteur du panneau
nf.debugbar.live flux en direct activé

Rien d’autre n’est stocké : aucun journal, aucune donnée d’application, aucune identité. L’état est versionné — si le format change, l’ancien est effacé au chargement plutôt que réinterprété, ce qui éviterait un état incohérent qu’on ne saurait pas défaire.

Options#

mountDebugBar({
  url: "/nodefony/studio/api/realtime", // adresse du canal temps réel
  client: maSocket, // socket déjà ouverte à partager
  position: "bottom", // ou "top"
  open: false, // panneau déplié au montage
  network: true, // requêtes de la page dans l'onglet Requêtes (instrumente fetch/XHR)
  env: "development", // environnement affiché avant toute mesure (posé par le serveur)
  page: { requestId }, // la requête qui a rendu la page (posé par le serveur)
});

mountDebugBar() est idempotent : une seule barre par page.

Accessibilité#

Tous les contrôles sont des boutons : ils s’atteignent au clavier, portent un nom et annoncent leur état (le replieur et le logo exposent aria-expanded, le temps réel aria-pressed). Leur nom est leur texte visible (WCAG 2.5.3), et leur cible fait 28 px de haut. La pastille réduite est un bouton, atteignable au clavier. Vérifié par axe-core sur la barre repliée et dépliée : aucun défaut. L’aide de chaque indicateur s’ouvre aussi bien au focus qu’au survol. La barre se déclare comme un contenu d’appoint (complementary), ce qui évite que tout ce qu’elle affiche soit compté hors de tout point de repère par un audit de la page hôte.

Coût#

La barre est une entrée séparée du paquet (nodefony/debugbar) : elle ne pèse rien sur une application qui ne l’importe pas. Son budget est vérifié à chaque publication (npm run size:check).

📖 Lexique#

Terme Ce que c’est
Entrée séparée Un sous-chemin du paquet (nodefony/debugbar) importé à part. Ce qui n’est pas importé n’entre pas dans votre bundle.
mountDebugBar La seule fonction à appeler (index.ts#mountDebugBar). Elle installe la barre et rend une poignée pour la piloter ou la retirer.
Poignée (handle) Ce que le montage rend en retour (DebugBarHandle, DebugBar.ts#DebugBarHandle) : de quoi fermer, rouvrir ou démonter proprement.
Options Ce qu’on passe au montage (DebugBarOptions, DebugBar.ts#DebugBarOptions) — l’adresse du socket, la position (bottom ou top), le panneau ouvert d’emblée, et l’interception réseau, qu’on peut refuser entièrement.
Charge utile Ce que le serveur pousse : statistiques (StatsPayload, model.ts#StatsPayload) et journaux (LogEntry, model.ts#LogEntry).
requestId L’identifiant qu’une requête porte de bout en bout. C’est lui qui relie une ligne de journal à l’appel réseau qui l’a produite.

⚠️ Pièges#

🧪 Tests & couverture#

Les chiffres exacts vivent dans la carte de l’aperçu, régénérée en comptant — jamais figés ici.

Type Où Ce qui est prouvé
Unitaires nodefony DebugBar.test.ts le montage, les options, ce que la poignée rend, le rendu des onglets
Unitaires (interaction) nodefony debugbarInteraction.test.ts l’ouverture et la fermeture, le filtrage des journaux, ce qui est gardé d’une visite à l’autre
Unitaires (onglet Requêtes) nodefony debugbarRequestsTab.test.ts, debugbarRequests.test.ts, debugbarFeedView.test.ts les trois vues sur le back des Journaux, le dépliage relu à la demande, le volet unique, les requêtes de la page jamais masquées, une liste fenêtrée qui ne bouge pas sous l’œil

🔗 Pour aller plus loin#