Apprentissage interactif avec Yjs
(learn.yjs.dev)- learn.yjs.dev est actuellement temporairement suspendu, il n’est donc pas possible de consulter le contenu pédagogique
- La page n’indique aucune raison de l’interruption, hormis le statut
This deployment is temporarily paused - Aucune date ni aucun calendrier de reprise du déploiement n’a été publié
- La structure, les fonctionnalités et les exemples du contenu d’apprentissage de Yjs ne sont pas consultables sur la page actuelle
- Le seul élément que l’on peut constater pour l’instant est que learn.yjs.dev est en état de suspension temporaire
1 commentaires
Commentaires sur Hacker News
Salut HN ! Je suis un développeur de Jamsocket et j’ai créé ça. Si vous ne connaissez pas Yjs, disons que c’est une bibliothèque CRDT pour créer des applications collaboratives et local-first
Si vous n’avez jamais manipulé d’état distribué, la courbe d’apprentissage est assez raide, et même quelque chose d’aussi simple qu’un compteur « hello world » dans une démo de framework JavaScript devient compliqué dès que plusieurs clients entrent en jeu
Beaucoup de tutoriels se résument à « installez cette bibliothèque et son intégration avec un éditeur de texte, et votre appli est prête », sans donner de modèle mental de ce qui se passe réellement
J’ai donc créé Learn Yjs, un tutoriel interactif sur Yjs, avec beaucoup de démos explorables et d’exercices de code pour que même les personnes qui découvrent le développement local-first puissent le comprendre intuitivement
Trouver un hébergement gratuit pour WebSocket semble aussi un peu plus difficile, et les tutoriels CRDT existants n’ont pas été d’une grande aide
Je travaille en HTML/JS pur et avec Alpine, et j’aimerais aussi savoir si on peut utiliser Yjs dans ce type d’application
Et j’aimerais aussi savoir si Y-Sweet fonctionne avec d’autres bibliothèques CRDT comme Automerge ou Loro, ou s’il est spécifique à Yjs
Comme tout le monde semble s’échanger des fichiers binaires avec une structure similaire, je me demandais jusqu’à quel point Y-Sweet est compatible avec des implémentations CRDT proches
[0] https://github.com/y-crdt/y-crdt
Yjs est bien, et il est facile d’obtenir des résultats en P2P
En revanche, le backend Yjs, la persistance, la résolution finale des conflits (par exemple lorsqu’un éditeur est resté hors ligne beaucoup trop longtemps) et le retour en arrière dans l’historique me semblent être des problèmes d’ingénierie difficiles à résoudre
J’ai toujours voulu une bonne expérience avec des éditeurs par blocs comme Platejs https://platejs.org/
C’est bien de voir des solutions comme Liveblocks https://liveblocks.io/text-editor essayer de simplifier l’expérience développeur, mais en général il faut renoncer à une partie du contrôle des données
Quand on cherche le mot-clé CRDT sur HN, on voit toujours de bons résultats et de l’intérêt, mais du côté des backends open source, je n’ai jamais vraiment vu de bonnes options. J’ai vérifié plusieurs fois par le passé, donc si j’ai raté quelque chose, je veux bien qu’on me le signale
https://hn.algolia.com/?dateRange=pastYear&page=0&prefix=tru...
La plupart des gens s’attendent à ce que cela fonctionne au minimum comme Google Docs ou Notion, et du point de vue développeur, ils veulent que ce soit stocké de façon opaque dans un format proche de Postgres JSONB sans avoir à creuser les détails d’implémentation
J’ai eu plusieurs fois envie d’utiliser Y.js avec un backend Go, mais il a toujours été difficile de trouver une implémentation de référence simple, et à cause des contraintes de temps, j’ai fini par abandonner à chaque fois
Même en revenant voir tous les quelques années, cela semble toujours difficile en dehors de Node.js
J’ai utilisé Yjs autrefois dans un petit side project. Côté client, c’était assez facile à apprendre et à utiliser
Côté serveur, je voulais déployer sous forme d’un binaire unique, mais il n’y avait quasiment aucun exemple dans des langages autres que Node, par exemple avec Yrs, le port Rust
J’ai finalement légèrement modifié https://github.com/yjs/y-websocket et ajouté une persistance basée sur LevelDB, mais à mes yeux ce n’était pas optimal
Je me demande s’il existe de bonnes ressources pour implémenter la partie serveur avec persistance dans un langage comme Rust
De mémoire, les ressources client existantes étaient très orientées intégration avec des éditeurs de texte, donc ce tutoriel est vraiment utile. Comme je n’utilisais pas d’intégration avec un éditeur de texte, j’ai dû avancer à tâtons
Il utilise S3 ou le système de fichiers local comme stockage, et se compile en un binaire de quelques Mo lié avec musl
https://github.com/jamsocket/y-sweet
On parle ici de « fractional indexing », c’est-à-dire la technique consistant à utiliser des fractions plutôt que des entiers pour les index, et je me demande combien de fois on peut l’utiliser avant que ça ne bloque
Le code de test est le suivant :
let left = 0, right = 1
let rightPrevious = 2
let counter = 0;
while (right > left && right < rightPrevious) {
rightPrevious = right;
right /= 2;
counter++
}
console.log(counter)
J’ai jeté un très bref coup d’œil au dépôt, mais je n’ai pas trouvé où ce problème est géré, et je n’avais pas le temps d’aller plus loin. Si c’est un vrai problème, je peux aider à le résoudre
En ce moment, j’utilise Yjs pour une application qui doit fonctionner hors ligne
Ce n’est pas à proprement parler une application collaborative en temps réel, mais si on considère le serveur comme un collaborateur et l’application comme un autre, on voit facilement le cas d’usage
Le point que je n’ai jamais réussi à dépasser avec Yjs, c’est que si on généralise l’exemple de déplacement d’éléments dans une app de liste de tâches de ce tutoriel, cela devient beaucoup trop complexe, beaucoup trop vite
Quand plusieurs objets ont des relations entre eux, on a naturellement envie de les mettre dans le même document, et maintenir ces relations dans un état synchronisé est semé de pièges, comme l’indexation fractionnaire du tutoriel
Puis, dès qu’on accumule des éléments à l’échelle d’une base de données, ce modèle jouet où tout est mis dans un seul document finit par signifier qu’il faut envoyer toute la base de données et son historique à quiconque veut lire n’importe quel élément
Au final, il faut séparer les éléments en objets distincts et les persister soi-même, mais à part ce tutoriel [0], il n’y a pas de documentation, et spoiler : c’est une page vide marquée depuis des années « Work in Progress - come back later »
Donc même si l’on veut créer et gérer un Provider, la situation côté documentation est la même [1]
On découvre les Subdocuments et on se réjouit en pensant qu’il existe peut-être une solution à ce problème courant [2], mais certains Providers ne gèrent pas les relations entre sous-documents, et d’autres ne prennent pas en charge les sous-documents eux-mêmes. On en revient donc à devoir créer son propre Provider, avec toujours le même problème : pas de documentation
Quand on essaie de lire le code, on finit par comprendre que le cœur de Yjs, ce sont les protocoles. Mais ces protocoles, qui sont pourtant l’essence même de Yjs, ne sont pas non plus entièrement documentés et sont disséminés dans plusieurs morceaux de code assez particuliers. À moins de considérer comme documentation un article académique sur le fonctionnement de l’ancêtre de Yjs il y a 10 ans
Ce n’était pas censé être un message de plainte, mais j’ai passé beaucoup trop de temps pendant des années à essayer de faire fonctionner tout ça, et l’écart est énorme entre les démos jouets du genre « ça marche comme par magie ! » et la création de quelque chose de réel. Et sur ce point, la documentation est restée vide pendant 10 ans, à part « Work in Progress »
J’espère que des entreprises comme celle de l’auteur de cet article, qui essaient de monétiser Yjs, aideront à combler cet écart
[0] https://docs.yjs.dev/tutorials/persisting-the-document-to-a-...
[1] https://docs.yjs.dev/tutorials/creating-a-custom-provider
[2] https://docs.yjs.dev/api/subdocuments
[3] En écrivant ce message, j’espérais que la situation avait changé, mais toute la documentation semble toujours en chantier comme il y a 5 ans, et la prise en charge des sous-documents aussi
Dans la démo interactive, le curseur de latence m’a dérouté parce qu’il se comporte comme un buffer de debounce plutôt que comme une latence réseau. Je ne comprends pas pourquoi ce choix a été fait
L’avantage de cette approche, c’est qu’elle peut être implémentée sans rien cacher au lecteur. Le diagramme circulaire expose directement le seul état interne qui existe
Le but n’était pas de simuler fidèlement un réseau, mais de construire une intuition
La démo interactive est magnifique. Je suis curieux de savoir quelles bibliothèques ont été utilisées pour la créer
Les démos exécutent réellement Yjs en interne. Chaque « client » a son propre document, et lorsque l’utilisateur clique, les documents sont fusionnés manuellement entre eux après simulation d’un délai avec
setTimeout. Il y a aussi un troisième document pour la timeline au centreSinon, la démo de liste de tâches utilise dnd kit [1] pour le glisser-déposer, Motion [2] pour les animations, et CodeMirror [3] pour l’éditeur de texte
[1] https://dndkit.com
[2] https://motion.dev
[3] https://codemirror.net
Le jeu avec l’image de bannière est idiot, mais amusant
Team purple ftw:
https://imgur.com/a/Oxc6jUA
J’ai enfin réussi à faire un trèfle à quatre feuilles, puis quelqu’un l’a gâché au bout d’environ deux minutes
Modification : attendez, où est passé tout le monde ? On dirait qu’on l’a cassé, ou bien que j’ai été bloqué. Bravo quand même à la personne qui l’a créé. C’est un super objet
Au passage, il y a encore deux emojis secrets