Une nouvelle version majeure de sigma.js

Sigma.js est une bibliothèque JavaScript de rendu de graphes. Elle a été créée par Alexis (de chez nous) il y a plus de 12 ans, et nous l’utilisons massivement chez OuestWare. Elle fait partie intégrante et de notre histoire, voire de notre identité : Paul (de chez nous) a embauché Alexis au médialab de Sciences-Po en 2013 pour développer la version 1.0 de sigma, et Benoît (de chez nous) a commencé à l’utiliser avant de rencontrer Alexis et Paul. Et nous l’intégrons maintenant dans environ un projet sur deux que nous produisons.

Une capture qui montre que le premier commit de sigma.js date de janvier 2012
Le premier commit de sigma.js !

Sigma.js v2.0

Après une première version d’essai développée en 2012, la version 1.0 de sigma a été développée par Alexis et Guillaume Plique au médialab, et a été publiée en 2014.

Guillaume et Alexis, au FOSDEM 2019
Guillaume et Alexis au FOSDEM 2019

À ce stade, on peut développer des applications web d’exploration et/ou de visualisation de réseaux très interactives, mais on manque d’outils. Il serait préférable de séparer les outils de rendu des outils de “traitement” de graphes. C’est pourquoi Guillaume crée Graphology en 2016. Il commence ensuite à développer une nouvelle version de sigma, qui ne fait que du rendu, et qui utilise graphology comme modèle de graphe, et pour tous les algorithmes.

Après la création de OuestWare, on commence aussi à utiliser cette version “officieuse” de sigma, jusqu’à ce qu’on décide, conjointement avec le médialab, à finaliser une version 2.0. En septembre 2021, on se réunit tous à Nantes, et on sort enfin cette nouvelle version, avec une toute nouvelle page vitrine conçue par Robin de Mourat.

Un problème de taille

En 2022, on commence à travailler sur Gephi Lite, et on commence à rencontrer certaines limitations de sigma, en particulier dans la gestion des tailles des nœuds et des arcs. En gros :

  • La taille des nœuds est interpolée entre des valeurs en pixels qui ne dépendent pas de la taille de la scène, contrairement à leurs positions ;
  • Les nœuds et les arcs grandissent “moins que le zoom” : quand on zoome d’un ratio R, ils grandissent d’un ratio sqrt(R).

Une animation qui montre que la variation de la taille des nœuds est parfois inattendue
Les nœuds sont plus serrés quand la scène est plus petite

Pour Gephi Lite, on avait besoin d’un meilleur contrôle de la taille des éléments, de sorte qu’ils soient dans le même référentiel que la position des nœuds, et qu’ils grossissent linéairement avec le zoom. Et nous n’étions pas les seuls. Malheureusement, le design des APIs des programmes dans sigma (c’est-à-dire le code qui indique comment tracer les nœuds et les arcs) ne le permettait pas, et pour pouvoir implémenter ces fonctionnalités correctement, il fallait d’abord casser l’existant.

C’est pourquoi, fin 2022, avec l’aide de Benjamin Ooghe-Tabanou, Alexis commence à reprendre la structuration de ce code ainsi que les traductions de coordonnées entre les différents référentiels, et Guillaume écrit une couche qui permettra de grandement simplifier l’écriture des programmes.

Mais on limite nos efforts : on ne veut pas précipiter une nouvelle version majeure de sigma, et on a tous pleins d’idées de fonctionnalités qu’on aimerait ajouter au passage. Et malheureusement, autant chez OuestWare qu’au médialab, sigma n’est jamais notre priorité du moment.

Un sponsor bienvenu

Une capture d'écran de G.V()
Une capture d'écran de G.V()

Début 2023, Arthur Bigeard, qui a un usage très avancé de sigma dans son application G.V(), nous contacte pour l’aider à améliorer son utilisation de sigma. Il utilise déjà la dernière version, et a découvert quelques fonctionnalités “cachées” de sigma que nous pensions être les seuls à utiliser (comme les expérimentations de Guillaume, par exemple). Après lui avoir détaillé les idées de fonctionnalités que nous avions en tête pour une nouvelle version de sigma, Arthur décide de nous embaucher pour avancer sur sigma. On fait des points réguliers avec lui, et il valide les fonctionnalités prioritaires sur lesquelles on doit mettre le plus d’efforts, mais on reste très libres de comment avancer.

Une roadmap chargée

On profite du gros chantier qui implique de casser les programmes pour réfléchir à ce qu’on peut/veut ajouter au passage :

  • L’instanced rendering pourrait réduire grandement l’empreinte mémoire des programmes. En gros, ça permettrait de n’envoyer qu’une fois les attributes qui change pour chaque élément et non pour chaque sommet (la couleur, la taille, etc.) ;
  • Le picking permettrait d’avoir la détection de collision avec tous les programmes, sans avoir à la calculer nous même. En plus, ça permettrait de supprimer toute la gestion du quadtree ;
  • Une gestion plus fine de l’indexation des données rendrait sigma bien plus performant dans de nombreux cas, en utilisant précisément les payloads des événements de graphology.

Aussi, on décide d’embarquer d’autres features qui nous tentent depuis longtemps :

  • On a enfin récupéré l’organisation @sigma sur NPM, donc on veut commencer à publier des packages “officiels” pour des extensions à sigma. Du coup, on restructurerait le projet en monorepo ;
  • On veut aussi améliorer le site Web, avec un Storybook (plutôt que les exemples dans CodeSandbox qui cassent trop régulièrement depuis la sortie de la v2), et avec une vraie documentation.

Sigma.js v3.0

On a pu bien avancer ces derniers mois. Pour résumer :

  • Alexis a implémenté le picking et l’instanced rendering dans les utilitaires de programmes, ainsi que sur tous les programmes existants ;
  • Benoit a lourdement optimisé la gestion des mises-à-jour. Maintenant, dans de nombreux cas, seules les index concernés sont modifiés, ce qui devrait augmenter les performances de sigma ;
  • Benoit a également implémenté le support des génériques TypeScript dans sigma, pour pouvoir clarifier le type du graphe ;
  • Alexis a sorti le node-image renderer et a intégré diverses fonctionnalités de la version de Guillaume, et c’est maintenant publié sous @sigma/node-image
  • Enfin, Alexis a pu reprendre le code de Guillaume dans ses expérimentations pour le tracé d’arcs courbes (fonctionnalité très demandée depuis longtemps), a ajouté le tracé des labels pour les arcs courbes, et a publié tout ça sous @sigma/edge-curve

Côté modernisation des tâches :

  • On a refactorisé le dépôt en monorepo, avec Lerna pour gérer la publication ;
  • On a remplacé Mocha par Vitest (pour pouvoir lancer les tests unitaires dans un environnement navigateur) ;
  • On a remplacé le code ad-hoc de Benoit par Playwright pour les tests end-to-end ;
  • On a remplacé les configurations Webpack datées du projet par Preconstruct (utilisé pour sigma, mais aussi les autres packages existants et à venir), et Vite pour la version minifiée de sigma pour les CDNs ;
  • On a migré la démo de Create React App vers Vite ;
  • On a écrit la nouvelle documentation, basée sur Docusaurus ;
  • On a migré le code ad-hoc de benchmark vers vitest bench, mais ça ne marche pas encore avec le browser mode (on surveille le ticket de près).

La page d'accueil de la nouvelle documentation de sigma
sigmajs.org/docs

Encore un grand merci à Arthur de G.V(). Sans son soutien, on n’aurait pas pu sortir cette version 3.0, en tout cas pas aussi vite.

Sigma v3 est encore en phase de test avant de publier une version non-beta, mais nous l’utilisons déjà dans plusieurs projets, et on est plus réactifs qu’avant sur la maintenance, vu que le code est plus frais (et nous aussi). Ce nouveau sigma devrait être moins gourmand en mémoire, probablement plus performant - on a hâte de pouvoir mesurer ça de manière fiable. Et on a enfin les arcs courbes, demandés depuis si longtemps \o/

Un graphe affiché avec sigma avec des arcs courbes
Les arcs courbes tant attendus