Journal Découvertes de logiciels libres - été 2023

17
11
nov.
2023

Sommaire

Cet été j’ai eu l’occasion de découvrir de belles pépites de logiciels libres grâce à un changement de travail. Ce nouveau travail était lié à l’affichage de données sur des cartes et des résultats dans des graphiques.

Voici une petite liste de logiciels libres que j’ai pu employer et que j’ai particulièrement appréciés 😊

PostgreSQL, postgis et node-postgres

PostgreSQL est une base de donnée à tout faire, vraiment. Je l’appréciais déjà auparavant pour ses fonctions intégrées de gestion des types JSON, text, large objects, le système pubsub, le système de full text search et ses extensions qui permettent la recherche imprécise (avec faute de frappe, sans casse), la création d’une hiérarchie simple avec un texte comme les path… et, surtout, sa documentation complète et compréhensible.

Cet été, j’en ai découvert une nouvelle facette avec l’extension postgis Elle permet à PostgreSQL d’enregistrer des données spatiales, de faire des calculs sur les polygones, de créer des rasters et de travailler sur leurs pixels…

node-postgres quant à lui est un client PostgreSQL crée pour Node.js. C’est bien un client SQL et non pas un ORM complexe: il s’occupe juste d’exécuter les requêtes et de transformer en type natif JavaScript ce qui est transformable (les données de type numeric, date, JSON…).

J’apprécie particulièrement qu’il n’essaie pas de faire de choses intelligentes comme gérer du cache ou créer des objets automatiquement: mine de rien, le fait que le client soit simple permet de le maitriser plus facilement (la courbe d’apprentissage est petite).

Un point que je trouve vraiment très fort est son plugin pg-query-stream qui permet de faire passer facilement à travers le réseau une requête qui génère des résultats de grande taille. Les Stream permet d’éviter de faire monter tous les résultats dans la mémoire de PostgreSQL et de celle de Node.js.

Curseur PostgreSQL ---[réseau]--> pg-query-stream -> JSONStream -> HTTP Response stream ---[réseau]--> HTTP client

Du côté de PostgreSQL, pg-query-stream utilise un curseur SQL pour récupérer les résultats à mesure que la requête s’exécute. Ensuite, du côté Node.js, pg-query-stream retourne un Readable Stream. Ce stream peut être enchaîné avec un Transformer Stream qui crée un objet JSON avec le résultat binaire de chaque ligne de réponse SQL. Enfin, ce stream peut lui-même être enchaîné avec le Writable Stream de l’objet HTTP Response de Node.js qui s’occupe d’envoyer au fur et à mesure les données au client HTTP (avec une réponse HTTP de type application/octet-stream).

Grâce à ce système de stream, il n’y a pas de surcharge mémoire quand une grande liste d’objet est demandée et ce ni sur le serveur PostgreSQL, ni sur le serveur de l’API. Le client HTTP quant à lui reçoit les premières données dès qu’elles sont prêtes, il n’aura pas besoin d’attendre de recevoir les données complètes avant de commencer la mise à jour de son affichage.

Node.js et ses stream

Ça fait maintenant 3 ans que je travaille avec Node.js (depuis la version 12) et j’apprécie beaucoup son API et son écosystème.

Il a bien sûr son lot de points négatifs comme le fait qu’un projet peu très facilement tirer des milliers de sous-dépendances. Pour ce point, les gestionnaires de dépendances font du bon travail et ne m’ont jamais posé problèmes (j’ai trouvé bien plus simple l’utilisation de npm et yarn que celles de pip et virtual env de Python ou celles de gem et bundler de Ruby).

La documentation de Node.js est vraiment très complète et bien structurée ! J’apprécie vraiment de pouvoir m’appuyer sur cette documentation pour bien appréhender ce qui est possible de faire et à partir de quelle version de Node.js.

Le système de stream de Node.js présenté plus haut est aussi plutôt bien pensé (ça ressemble au fonctionnement des pipes de Linux) et je l’apprécie beaucoup, car il permet également de créer ses propres streams facilement. Il y a pas mal de documentation à lire quand on implémente pour la première fois une extension de Readable et Writable, mais le code final est bien organisé: les classes de base de Node.js s’occupent de la gestion du stream et les classes d’extensions ne s’occupent que de la lecture ou l’écriture des données.

Par exemple, j’ai eu besoin d’importer dans PostgreSQL un historique de donnée sous format CSV avec un traitement à effectuer entre deux. Le fichier CSV avait tellement de donnée qu’il dépassait la limite de lignes lisibles par LibreOffice Calc.

Pour lire le CSV, j’ai donc utilisé l’outil csv-parser qui permet de lire le fichier avec un Readable Stream.

En implémentant les fonctions _write et _final, j’ai été capable de créer un Writable Stream qui prépare les requêtes nécessaires en lisant les données et les envoient régulièrement en bloque au serveur PostgreSQL.

Enfin, il faut chainer les deux Stream pour avoir un outil qui puisse lire le CSV tout en envoyant à mesure de la lecture les requêtes SQL pour enregistrer les nouvelles données en base.

Frontend avec Vue.js 3

J’ai pour la première fois créé le frontend d’une application avec un framework JavaScript. J’ai trouvé que Vue.js est un cadriciel qui permet de bien structurer son application et qui aide à faire les liens entre les éléments DOM et le code JavaScript de manière efficace.

De nouveau, sa documentation est bien faite et elle n’est pas trop longue à lire.

Vue.js m’a permis de découvrir comment bien utiliser la composition pour éviter de créer des hiérarchies complexes d’objets tout en gardant un code avec peu de répétitions.

Un autre point appréciable est qu’il est plutôt aisé de créer un Component qui intègre des outils JavaScript qui n’ont pas été développés pour Vue.js. Par exemple, mes collègues ont pu intégrer de manière efficace des outils complexes comme OpenLayers et Chart.js.

Pour ma part, j’ai pu faire l’intégration de noUiSlider pour permettre aux utilisateurs d’utiliser ce curseur avancé pour naviguer à travers des graphes de données temporelles. Pour faire cette intégration, je me suis reposé sur Vueform slider, parce que j’avais d’abord trouvé cet outil. Ce n’est que plus tard que j’ai découvert qu’il était une intégration de noUiSlider dans Vue.js. Si c’était à refaire, je ferai directement l’intégration de noUiSlider pour avoir plus de souplesse (j’avais une limitation sur l’intégration des pips que Vueform slider n’avait semble-t-il pas prévu dans son intégration).

OpenLayers

OpenLayers est un projet complexe qui permet d’intégrer une carte du monde dans son site web et d’ajouter au-dessus des couches interactives. Le sujet étant lui-même complexe, je trouve qu’OpenLayers est un très bon projet et qu’il aurait été difficile de faire plus simple.

J’ai été impressionné de réussir à intégrer des objets SVG et dynamiques dans le <canvas> d’OpenLayers.

Un souci que nous avions était de réussir à faire télécharger des images d’un serveur d’image avec un token d’authentification à ajouter dans un Header HTTP. Or le navigateur n’avait pas lui-même authentifié l’utilisateur: il ne pouvait donc pas lui-même se charger de passer du bon en-tête Authorization. On ne pouvait pas simplement utiliser l’API Fetch du navigateur non plus, car on devait lui dire d’ajouter pour chaque requête du bon en-tête.

Eh bien, OpenLayers est assez souple pour lui donner une méthode alternative pour télécharger les images et le faire de manière authentifiée grâce au module axios que nous utilisions déjà pour les autres requêtes vers notre API.

Chart.js

Chart.js est un outil que j’ai eu assez de peine à comprendre comment bien l’utiliser. Il permet d’intégrer un graphique avec des données dans un <canvas>.

Sa documentation est plutôt fouillis et il est difficile de trouver la page qui donnera la bonne information sur la configuration.

Cependant, quand j’ai commencé à comprendre leur philosophie pour la configuration et les bons termes pour les parties que je voulais changer, j’ai trouvé que l’outil était plutôt bien fait.

Le graphe de base n’est pas dynamique, mais j’ai pu l’assembler avec le curseur noUiSlider pour mettre à jour dynamiquement les bornes d’affichage de l’axe x. Là, j’ai découvert que Chart.js fait très bien son travaille et qu’il arrivait de manière fluide à suivre les mises à jour que le curseur lance durant son glissement.

noUiSlider

Durant mon projet, j’avais besoin de créer un ascenseur horizontal pour naviguer à travers des dates sur 3 ans.

En lisant MDN , j’ai appris que HTML 5 proposait déjà un <input type="range"> pour créer un slider sur des valeurs numériques. La documentation donne même un exemple avec <datalist> pour lier des textes à des valeurs numériques.

J’étais assez emballé par cet outil, mais malheureusement, il ne permet pas beaucoup de stylisation et je ne pouvais donc pas facilement l’intégrer dans notre application web et supporter plusieurs navigateurs.

En plus, j’avais besoin d’un slider qui permette de choisir deux valeurs pour définir un range de date à visualiser et non pas juste une seule date.

noUiSlider est un outil JavaScript qui permet de créer des sliders avec beaucoup plus de flexibilité et, surtout, permet de le styliser de manière simple.

noUiSlider est beaucoup plus précis pour l’affichage des marqueurs et des textes puisqu’il gère lui-même toute l’intégration avec le slider.

A contrario, l’exemple de la documentation MDN (avec HTML et CSS) utilise une flexbox de CSS pour répartir de manière proportionnelle les valeurs de <datalist> sur la même largeur que l’élément <input>. Comme les affichages de ces deux éléments HTML ne sont pas vraiment liés, il est très difficile de placer les marqueurs de manière exacte et il est nécessaire d’avoir toujours un espace équivalent entre chaque marqueur.


PS: Cet article a été originalement publié sur mon nouveau blog statique (cf. mon site web personnel). Sur ce blog, j'ai repris certains journaux et dépêches que j'avais écrits sur LinuxFr. J'espère y écrire de manière régulière et pas forcément sur du logiciel libre, vous pouvez suivre mon compte Mastodon ou le flux RSS si ça vous intéresse.

  • # blog

    Posté par  (site web personnel, Mastodon) . Évalué à 3.

    C’est sympa les méta et leur rendu.

    J’allais demander si tu avais reproduit les spécifications du markdown de linuxfr mais je vois que sur ton blog le HTML intégré suivant n’a pas été viré.

    <form style="margin: auto; max-width: 50%">
        <input
            style="
                width: 100%;
                accent-color: hsl(var(--link-text-color-hsl) / 100);
            "
            list="exemple-range"
            type="range"
            min="10"
            max="50"
        />
        <datalist
            id="exemple-range"
            style="
                width: 100%;
                display: flex;
                flex-direction: column;
                justify-content: space-between;
                writing-mode: vertical-lr;
            "
            >
            <option value="10" label="minimum"></option>
            <option value="30" label="moyen"></option>
            <option value="50" label="maximum"></option>
        </datalist>
    </form>

    “It is seldom that liberty of any kind is lost all at once.” ― David Hume

    • [^] # Re: blog

      Posté par  (site web personnel, Mastodon) . Évalué à 3. Dernière modification le 11 novembre 2023 à 22:39.

      J’allais demander si tu avais reproduit les spécifications du markdown de linuxfr mais je vois que sur ton blog le HTML intégré suivant n’a pas été viré.

      Pour chaque article de mon blog, j'écris du HTML directement avec l'aide de prettier dans vim.

      En fait, si tu regardes la source de la page d'un article, c'est quasiment le fichier qui se trouve sur mon git: https://gitlab.adorsaz.ch/adrien/adorsaz.ch/-/blob/bf2aa989380be32f99d51e1520d8ce1b99e92854/src/articles/decouvertes-logiciels-libres-ete-2023.html

      J'avais à cœur que le fichier HTML codé soit un fichier complet et donc auto-suffisant si JavaScript n'est pas activé. C'est très pratique car je peux dire à Firefox d'ouvrir le fichier directement pour prévisualiser sans avoir besoin d'étape supplémentaire ou de serveur web.

      Seulement, je ne voulais pas non plus répéter l'en-tête du blog dans chaque page d'article. Comme je n'ai pas de moteur de template, ce que j'ai fait, c'est que le code JavaScript d'article.js injecte l'en-tête du blog dans l'article.

      C’est sympa les méta et leur rendu.

      Merci :) C'est justement dans la suite de cette idée: je voulais donner les méta dans le fichier HTML directement sans avoir besoin de me répéter. Donc pour les lecteurs qui activent JavaScript je leur en fait une présentation sous le titre et pour les autres je leur avertit que c'est disponible dans les balises meta du code source.

      J’allais demander si tu avais reproduit les spécifications du markdown de linuxfr

      Pour écrire le journal, j'ai donc du traduire l'HTML vers son markdown. Ça se fait assez bien à la main, l'article n'est pas trop long. Effectivement, le markdown ne permet pas de tout avoir, j'ai dû laissé tombé l'exemple du form et j'ai juste référé à l'exemple de la documentation de Mozilla.

      • [^] # Re: blog

        Posté par  . Évalué à 6.

        Comme je vois que tu utilises nginx pour ton site perso tu pourrais aussi utiliser des Server-Side Includes. C'est un peu démodé mais tu peux juste avoir un commentaire dans le HTML du type <!--# include file="header.html" --> et voilà, pas besoin de javascript du tout.

        • [^] # Re: blog

          Posté par  (site web personnel, Mastodon) . Évalué à 2.

          Je ne connaissais pas cette fonctionnalité, merci !

          C'est sympa comme petit moteur de template.

          Je trouve que c'est pas mal, parce que le fichier HTML sera complet dès la réception par le navigateur.

          Je vois qu'Apache le supporte aussi. Mais c'est un peu plus dangereux de l'activer, parce qu'il permet aussi d'exécuter un shell.

          • [^] # Re: blog

            Posté par  (Mastodon) . Évalué à 4.

            Je vois qu'Apache le supporte aussi. Mais c'est un peu plus dangereux de l'activer, parce qu'il permet aussi d'exécuter un shell.

            C'est débrayable : You can allow SSI, but not the exec feature, with the IncludesNOEXEC argument to the Options directive.

            • [^] # Re: blog

              Posté par  (site web personnel, Mastodon) . Évalué à 2.

              Tu m’as devancé :) Je me souviens d’avoir été confronté à la problématique il y a quelques années pour un site interne de documentation de code.

              “It is seldom that liberty of any kind is lost all at once.” ― David Hume

      • [^] # Re: blog

        Posté par  (site web personnel, Mastodon) . Évalué à 3.

        Ah oui, je n’avais pas vérifié (je viens de télécharger le markdown et effectivement ce formulaire n’y est pas.) J’avais bêtement pensé que tu sauvegardes le source LinuxFr et utilises un SSG (c’est à la mode.) À défaut, du coup, pour le templating simple, il y a les SSI évoqués dans un autre commentaire.

        Ça fait plaisir de voir qu’il y en a qui font encore du HTML à manuellement (ça veut souvent dire au passage qu’on fait aussi simple que le voudrait Gemini… mais on peut rajouter plus de sémantique par endroit —pour ma part c’est souvent des µF…)

        “It is seldom that liberty of any kind is lost all at once.” ― David Hume

  • # SQLPage

    Posté par  (site web personnel) . Évalué à 4.

    Si je peux me permettre une petite pub pour un autre logiciel libre, chouette à utiliser sur ce genre de projets: SQLPage, et son composant map, est très pratique pour afficher des données d'une base PostGIS sur une carte, avec la possibilité de créer ses propres options de filtrages et de visualisation.

    • Avantages: c'est beaucoup plus rapide à construire, plus simple à mettre en place et à maintenir.
    • Inconvénients: c'est moins flexible que de tout réaliser à la main avec un backend sur-mesure en node et un frontend sur-mesure en vue.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.