Skip to content

Aller plus loin dans NodeCG

Vous avez maintenant les bases pour créer un bundle NodeCG fonctionnel !

Si le bundle d’initiation présente est relativement simple, en pratique, plus un projet grossit, plus on rencontre de nouvelles problématiques : organisation du code, outils de développement, réutilisation de composants, gestion des données, déploiement…

Cette partie rassemble donc quelques astuces, réflexions personnelles et pistes pour aller plus loin. Il ne s’agit pas de règles à suivre absolument. Ce sont surtout des choses que j’ai découvertes ou mises en place avec l’expérience.

J’utilise régulièrement NodeCG pour aider à la réalisation d’événements.

Sur mon PC de développement, tout mon environnement est déjà installé : Node.js, NodeCG, les dépendances du projet, Git, etc.

Le problème arrive lorsqu’il faut déplacer le setup sur un autre ordinateur, comme le PC utilisé pour le stream.

Il n’est pas forcément possible ou souhaitable d’installer tout l’environnement de développement sur cette machine, surtout quand les bénévoles n’ont derrière n’ont pas trop d’expérience dans ses outils.

Le but est d’être le plus simple possible : on clique sur un script et tout se lance et fonctionne.

  • Directorybundle-evenement/
    • Directorydashboard/
    • Directorygraphics/
    • Directoryextension/
    • Directorygit/
    • node.exe
    • lancement.bat

Je peux alors copier ce dossier sur une clé USB, le transférer sur le PC de l’événement et lancer NodeCG sans avoir à réinstaller tout l’environnement.

Ce n’est pas la solution la plus élégante pour tous les projets, mais pour un setup événementiel qui doit pouvoir être déplacé rapidement, ça peut être très pratique.

Faites attention à la déclaration des Replicants

Section titled “Faites attention à la déclaration des Replicants”

À mesure qu’un bundle grossit, on peut se retrouver à déclarer le même Replicant dans beaucoup d’endroits.

Au début, cela ressemble à ceci :

const scoreboardRep = nodecg.Replicant("scoreboardRep", {
defaultValue: {
// ...
}
});

Puis, quelques fichiers plus loin, on redéfinit à nouveau sa structure un peu différemment et ainsi de suite. Le problème est qu’à force de faire cela, les différentes déclarations peuvent finir par ne plus être parfaitement cohérentes.

Une solution que j’utilise est de définir la structure de mes Replicants avec un Schema JSON.

Un Schema JSON décrit la structure attendue d’un Replicant et de valider les données qui y sont stockées. Cela devient particulièrement utile lorsque les Replicants deviennent complexes ou sont utilisés à de nombreux endroits.

Cela permet notamment de centraliser la structure attendue d’un Replicant et de bénéficier d’une validation des données.

Par exemple, notre Replicant scoreboardRep pourrait être décrit avec le schéma suivant :

{
"$schema": "http://json-schema.org/draft-07/schema",
"type": "object",
"default": {
"team1": {
"name": "Team 1",
"score": 0
},
"team2": {
"name": "Team 2",
"score": 0
},
"isVisible": true
},
"properties": {
"team1": {
"type": "object",
"properties": {
"name": {
"type": "string" // Attends une chaîne de caractères
},
"score": {
"type": "number" // Attends un nombre
}
}
},
"team2": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"score": {
"type": "number"
}
}
},
"isVisible": {
"type": "boolean"
}
}
}

C’est la même structure que dans le Replicant présenté dans le guide : deux équipes avec un nom et un score, ainsi qu’une propriété visible.

Comme le Replicant est défini dans une structure de référence, je peux l’appeler plus facilement dès que je ai besoin :

const scoreboardRep = nodecg.Replicant('scoreboardRep')

L’intérêt devient surtout visible lorsque le Replicant devient plus complexe. Le schéma permet de décrire précisément la forme des données attendues et d’éviter certaines erreurs.

Le bundle de ce guide est volontairement très simple

Section titled “Le bundle de ce guide est volontairement très simple”

Le bundle proposé dans ce guide utilise volontairement des technologies très basiques : HTML, CSS et JavaScript.

C’est un bon point de départ pour comprendre NodeCG, mais vous n’êtes absolument pas obligé de rester sur cette structure.

NodeCG n’impose pas de rester sur du JavaScript “vanilla”, si vous aimez TypeScript, des bundlers (Vite, Parcel…) ou des frameworks (React, Vue, Svelte…) spécifiques, faites-vous plaisir !

Personnellement, mon stack habituel ressemble plutôt à ça :

  • TypeScript : une version de JavaScript qui permet notamment de typer les données et de détecter certaines erreurs plus tôt
  • Svelte : un framework permettant de construire des interfaces à partir de composants réutilisables
  • Vite : un outil qui s’occupe notamment de transformer et préparer le code de l’application pour qu’il puisse être utilisé dans le navigateur

Par exemple, avec Svelte, je peux créer des composants d’interface réutilisables :

  • Directorycomponents/
    • Button.svelte
    • ScoreInput.svelte
    • Selector.svelte
    • Modal.svelte

Lorsque je crée ensuite un nouveau Dashboard, je peux réutiliser directement ces composants plutôt que de recréer chaque élément d’interface, c’est un sacré gain de temps !

NodeCG permet également d’utiliser plusieurs bundles au sein d’une même instance. Plutôt que de tout mettre dans un seul bundle gigantesque, vous pouvez séparer les fonctionnalités ou les usages en plusieurs bundles.

On peut par exemple avoir une structure de ce genre :

  • Directorybundle-jdr/
    • Directorydashboard/
    • Directorygraphics/
    • Directoryextension/
    • Directorybundles/
      • Directorycampagne-x/
      • Directorycampagne-y/

Le bundle-jdr contient la logique générale (connexion à FoundryVTT, récuperation et stockage des données, outils de réalisation…), les sous-bundles contiennent les assets des personnages, les scripts spécifiques à cette campagne…

Ici, un bundle peut contenir les outils communs au jeu de rôle, tandis que d’autres sont dédiés à une campagne particulière. L’intérêt est surtout de garder des projets plus faciles à comprendre et à maintenir.

C’est probablement l’un des points qui a le plus changé ma manière de développer avec NodeCG.

Au début, j’avais tendance à construire mes outils principalement autour des Dashboards, des Graphics et des Replicants. Puis, en comprenant mieux la partie serveur de NodeCG et ce qu’il était possible de faire depuis une Extension, ma façon de concevoir mes bundles a complètement changé.

L’Extension permet notamment de déplacer une partie de la logique côté serveur et de faire des choses qui n’ont pas vraiment leur place dans une interface ou un Graphic.

Ne faites donc pas l’impasse sur cette partie. Même si vous n’en avez pas besoin pour votre premier bundle, prenez le temps de comprendre à quoi elle sert et ce qu’elle permet.

Avec l’expérience, vous découvrirez probablement que certaines choses que vous essayiez de faire depuis un Dashboard deviennent beaucoup plus simples une fois déplacées dans l’Extension.

C’est aussi ce qui rend NodeCG particulièrement intéressant : on ne construit pas seulement des interfaces graphiques, on peut véritablement construire un petit système complet autour de Node.js.

Une erreur assez classique consiste à avoir un nom de dossier qui ne correspond pas à celui déclaré dans le package.json.

Par exemple : le nom du dossier est bundle-initiation mais le nom déclaré dans le package.json est initiation-bundle

Une petite différence peut suffire à empêcher NodeCG de charger correctement le bundle.

Aucun fichier HTML dans dashboard ou graphics

Section titled “Aucun fichier HTML dans dashboard ou graphics”

Pour qu’une page puisse être chargée, NodeCG doit pouvoir trouver un fichier HTML dans le dossier concerné.

Si vous avez créé un dossier dashboard ou graphics, mais qu’il ne contient aucun fichier HTML, NodeCG ne pourra rien afficher.

Vous aurez probablement une erreur au lancement de NodeCG dans ce cas-là.

Souvent même si le fichier HTML existe et déclaré dans le package.json, NodeCG retournera une erreur si le fichier est encore vide.

Pour éviter l’erreur, quoiqu’il arrive, j’ajoute toujours une structure minimale.

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Mon Dashboard</title>
</head>
<body>
</body>
</html>

Le nom du fichier ou le chemin ne correspond pas

Section titled “Le nom du fichier ou le chemin ne correspond pas”

Une autre erreur assez classique concerne le nom des fichiers.

Le nom du fichier utilisé dans votre configuration doit correspondre au fichier réellement présent dans votre bundle.

Par exemple, si votre package.json indique :

{
"nodecg": {
"dashboardPanels": [
{
"name": "scoreboard",
"title": "Scoreboard",
"file": "scoreboard.html"
}
]
}
}

NodeCG va chercher dashboard/scoreboard.html.

Si le fichier se trouve en réalité dans dashboard/scoreboard/scoreboard.html, il faut alors indiquer le chemin correspondant :

"file": "scoreboard/scoreboard.html"

De la même manière, une différence dans le nom du fichier (scorebaord.html, Scoreboard.html, index.html…) empêchera NodeCG de trouver le fichier attendu.