veilletech.fr
24 sept. Feed du jour
#07 FRONT Article

GitHub : une PR d'un million de lignes, sans saccade

Un observateur qui écrit ce qu'il observe finit par ne plus observer que lui-même.

GitHub détaille la refonte de la vue des pull requests de son application Copilot, testée sur un diff de 2 200 fichiers, plus d'un million de lignes et plus de 400 commentaires. La clé : séparer la géométrie exacte du code de celle, mesurée à la volée, des commentaires, et remplacer les ResizeObserver qui réécrivaient les hauteurs par une passe de mesure unique, déclenchée à l'arrêt du défilement.

4 min de lectureavancévidéo 1:22
Partager
Sommaire8 sections
  1. Ce qui se passe
  2. Ce qui marchait déjà pour le code
  3. Le problème des commentaires
  4. Deux géométries
  5. L'erreur qu'ils ont d'abord commise
  6. Ancrer par identité, pas par pixel
  7. Côté données et outillage
  8. À retenir

Ce qui se passe

GitHub a reconstruit la vue des pull requests de son application Copilot pour qu'elle reste fluide sur les très gros changements. Le banc d'essai : une pull request open source de 2 200 fichiers, plus d'un million de lignes modifiées et plus de 400 commentaires en ligne. Alberto Gimeno, qui signe le billet, en tire des règles qui valent pour toute liste virtualisée à hauteur variable.

Ce qui marchait déjà pour le code

Un diff d'un million de lignes ne tient pas dans le DOM. La réponse classique est la virtualisation : une centaine de lignes seulement sont montées, et recyclées pendant le défilement. Tout le reste est de l'arithmétique sur une table de hauteurs. Comme chaque ligne de code a la même hauteur, cette table se calcule d'avance et ne change jamais. GitHub a gardé tout ce socle : un rendu impératif sans composant React par ligne, des tableaux typés pour les décalages, un diff envoyé structure d'abord, et une API « défiler jusqu'à la ligne N ».

Le problème des commentaires

Un fil de revue n'a pas de hauteur connue avant d'être rendu : elle dépend du retour à la ligne du markdown, d'un bloc <details> déplié, d'un champ de réponse qui grandit à la frappe, d'une image qui finit de charger. Réserver une hauteur estimée laisse des trous ou coupe les longs fils. Corriger après coup décale tout ce qui suit, pendant que l'utilisateur fait défiler.

Deux géométries

La solution est de ne plus forcer une seule géométrie à tout porter :

TEXT
hauteur totale = hauteur du code        (exacte, calculée d'avance)
               + Σ hauteurs des blocs   (estimées, puis mesurées)
               + marge de défilement

Chaque commentaire devient un bloc identifié par ce qu'il est, pas par sa position : une clé stable, un ancrage sur fichier, ligne et côté du diff, une empreinte de tout ce qui peut changer sa taille, et la largeur de la dernière mesure, arrondie par paliers pour qu'un simple redimensionnement n'invalide pas tout. Sa hauteur est la mesure si elle est valide, sinon une valeur en cache si empreinte et largeur correspondent, sinon l'estimation. Ces hauteurs vivent dans leur propre index : un commentaire qui grandit ne reconstruit jamais la géométrie du code.

L'erreur qu'ils ont d'abord commise

Le premier réflexe, un ResizeObserver par bloc qui réécrit la hauteur mesurée, a été rejeté : un observateur qui modifie la mise en page de l'élément qu'il surveille peut se redéclencher lui-même, et le coût croît avec le nombre de blocs. À la place :

Ancrer par identité, pas par pixel

Avant chaque correction, on note l'élément regardé et le décalage à l'intérieur ; on applique les nouvelles hauteurs ; on retrouve la nouvelle position de cet élément et on défile pour qu'il reste en place. Un bloc au-dessus de l'écran qui change de taille est compensé, un bloc en dessous ne l'est pas.

Le piège le plus instructif : la garde « ne pas corriger pendant que l'utilisateur défile » se basait sur le dernier défilement observé, que les défilements programmatiques rafraîchissaient aussi. Ouvrir la barre latérale élargissait le diff, provoquait un petit défilement interne, et la correction censée garder la place sautait. Leur règle : un test « l'utilisateur interagit-il ? » ne doit jamais pouvoir être satisfait par vos propres effets de bord.

Côté données et outillage

La coloration syntaxique tourne hors du thread principal, les derniers diffs visités restent en cache, et des sondes permanentes vérifient en test de bout en bout des budgets chiffrés : nombre de blocs montés, une seule écriture par frame, taille des corrections, observateurs bien déconnectés. Une boucle automatique pilotait l'application et écrivait ses mesures sur disque, où un agent les lisait sans humain au clavier.

Source : Rendering huge pull requests in the GitHub Copilot app, Alberto Gimeno, GitHub Blog, 23 septembre 2026.