Deep Dive 121 –
SolidJS mit Fabian Hiller
24.03.2023
- // Podcast
- // Deep Dive 121
Shownotes
SolidJS ist ein Frontend-JavaScript-Framework, das die gleichen Probleme lösen kann wie React oder Vue.js, aber auf Virtual DOM Diffing verzichtet, wodurch es besonders performant ist. Chirurgische DOM Updates erreicht man bequem mit Signals. In dieser Folge geben wir euch gemeinsam mit unserem Gast Fabian Hiller einen Überblick über SolidJS und seine Features und sprechen detailliert über das Reaktivitätskonzept der Signals.
Fabian Hiller kennst du bereits aus dem News-Format und Deep Dives über Next.js oder React. Für SolidJS hat er eine Open-Source-Bibliothek für Formular-Validierung veröffentlicht und wird so zum perfekten Ansprechpartner für dieses Thema.
/transkript/programmierbar/deep-dive-121-solidjs-mit-fabian-hiller
Hallo.
Und herzlich willkommen zu einer weiteren Folge der Programmierbar. Wir haben mal wieder ein Deep Dive für euch und wir, das sind heute der Fabian und neben mir sitzt der Liebe.
Hi!
Und wir reden heute über SolidJS und wir reden über SolidJS mit keinem weniger als unserem lieben Fabian Hillerhei.
Halli, hallo! Genau, wir unterhalten uns über SolidJS. Schön, dass du mal wieder hier bist. Wir sitzen direkt hier zusammen. Wer deinen YouTube-Kanal verfolgt hat, hat ja gesehen und auch unseren Gespräch, dass du auch in Amerika warst und jetzt wieder hier bist bei uns. Aber leider nur für sehr kurz. Da wird es bestimmt gleich noch ein bisschen mehr erzählen, was du da jetzt gerade so machst. Aber vielleicht, bevor wir auf dich noch mal eingehen, kannst du uns kurz und knapp erklären, was ist SolidJS?
Ganz, ganz einfach gesagt ist SolidJS eine deklarative JavaScript Bibliothek zum Erstellen von Benutzeroberflächen, so wie React, View und so weiter und hat erst mal auch das gleiche Feature Set wie React, View und Co. Das heißt, man kann State definieren, die UI aktualisiert sich, wenn sich das State ändert. Man hat Dinge wie SideEffects bei React mit UseEffect, bei SolidJS mit GradeEffect, was der Unterschied ist zwischen Solid und den meisten anderen JavaScript Frameworks und Libraries ist, dass kein virtuelles Dom verwendet wird für die Aktualisierung des echten Doms, sondern Solid nutzt eine fein Granulare Reaktivität, die einzelnen Dom Nodes direkt zu aktualisieren. Und das hat dann auch wieder den Vorteil, dass es sehr performant ist. Und da gehen wir bestimmt auch noch drauf ein. Man hat die Performance Out of the Box bei Default. Man muss nicht wie bei React gegebenenfalls Optimierungen vornehmen mit eigenen APIs, also mit zum Beispiel Memo oder mit weiteren APIs, die es da gibt. Dadurch führt Solid aktuell einige der Runtime Performance Benchmarks an. Und vor allem jetzt auch durch die Signals, auf die wir bestimmt auch noch eingehen, hat Solid so einen kleinen Hype und die Communities grad stark am Wachsen und immer mehr entsteht und auch immer mehr Firmen versuchen sich in Solid aus.
Aktuell noch sehr viel mit Astro und in der Zukunft bestimmt auch mit dem eigenen Meta Framework Solid statt.
Und wenn es jetzt gerade ein Hype wird, weißt du, kannst du sagen, wie lange gibt es das schon so? Von wem kommt es? Aus welcher Feder? Und wie lange gibt es das schon?
Genau. Also SolidGS stammt von Ryan Cardiado. Das ist der Autor hinter SolidGS, der davor an Marco gearbeitet hat. Das ist auch von Ebay. Vielleicht spreche ich es aber falsch aus. Die Leute, die es kennen, die wissen, was ich meine. Und der hat 2016 damit begonnen, an Solid Shares zu arbeiten. Und soweit ich weiß, wurde dann 2018 das Ganze Open Source of GitHub. Und mittlerweile, also Ryan hat es immer so ein bisschen nebenher gemacht und mittlerweile ist er angestellt bei Netlefy und kann Vollzeit an Solid Shares arbeiten.
Ach cool. Okay. Das klingt ja auf jeden Fall schon mal super cool. Vielleicht vorab, bevor wir auf SolidJS und die Features ein bisschen eingehen. Wie kommt es jetzt eigentlich, dass du über SolidJS sprichst? Weil ich glaube, beim letzten Mal hatten wir dich zu React, bist du einbist du abgewandert? Was machst du gerade so?
Kann man so ein bisschen sagen. Also gestartet bin ich in React und da hatte ich lange Zeit auch das tiefste Wissen. Da hatte ich die meiste Erfahrung. Da habe ich die größten und komplexesten Anwendungen gebaut. Dann hatte ich ja auch mal einen Ausflug hier in der Programmierbar mit View für die Programmierbar Website.
Das ist die schöne Welt mal kennengelernt.
Und dann? Tatsächlich. Also wenn ich ganz ehrlich bin, fand ich viele Dinge an React besser, was die Developer Experience angeht. Ich bin nicht so ein Fan von den Templates und auch wie die API funktioniert, fand ich bei React besser und auch das Ökosystem hat auf mich den Eindruck gemacht, als wäre es ein bisschen weiter ausgereift von den Open Source Projekten, die es drumherum gibt. Dann stand ich, das war Mitte 2022, wieder vor einem neuen Projekt. Und zwar arbeite ich aktuell an einer eigenen E-Learning Plattform, wo ich in der Zukunft meine Inhalte auf Englisch veröffentlichen möchte. Und ursprünglich war die Idee, da gehe ich jetzt nicht ganz strukturell vor. Ich nutze alles, was ich halt kann und weiß, baue das schnell und konzentriere mich halt wirklich auf das, was wichtig ist und fang nicht an, wieder irgendwelche Experimente zu machen. Und ich habe tatsächlich erst mal meinen Plan befolgt, habe NextGS genutzt, dann auch Direktos, was ich von der Programmierbar dann kannte und irgendwann, also ich hatte schon mal in der Zeit, wo ich dann tatsächlich hier war, mir das halt angeschaut, aber habe es nicht so ganz verstanden und dann immer wieder mal habe ich noch mal einen Blick draufgeworfen.
Und dann kam das war irgendwann Richtung Ende Sommer oder Herbst 2022 der Punkt, da habe ich es mir mal genauer angeschaut und dachte ich mir so, so dumm ist es gar nicht. Weil ich fand React so von der Developer Experience echt immer super. Und da ich mittlerweile auch ein sehr tiefes Verständnis dafür entwickelt habe, bin ich auch super damit zurechtgekommen und auch super schnell in der Entwicklung gewesen. Aber es gab immer so ein paar Punkte, die mich irgendwie dann doch gestört haben. Zum Beispiel, wenn wir jetzt ein Formular haben und da irgendwas eintippen und das Ganze 'controlled' ist, also der State des Forminars von React kontrolliert wird, dann muss React die ganze Zeit, im Grunde die ganze App, je nachdem wo das Formular liegt, aber die Komponente und die darunterliegenden Komponenten neu rendern, obwohl eigentlich nur ein Formular kleines Textfeld sich verändert hat. Und ich dachte, das geht doch bestimmt irgendwie besser. Aber habe eigentlich nie so drüber nachgedacht, wie und was man da so machen könnte und was es vielleicht auch noch so gibt. Und dann kam mal 'Solid S' und dann dachte ich mir, oh, die lösen das ja ziemlich gut. Dann habe ich halt für mich irgendwie zum einen die Chance gesehen, da wieder was Neues zu lernen, auch vielleicht ein bisschen Pionierarbeit zu tun, weil ich hatte schon immer den Wunsch, mal ein Open Source Projekt zu starten und habe dann die Chance gesehen, da die SolidGS Community aktuell noch kleiner ist oder im Vergleich zu React noch sehr sehr klein, da vielleicht einen Impact zu haben mit einem eigenen Open Source Projekt.
Und dann hat irgendwie eins zum anderen geführt. Ich habe ein Open Source Projekt umgesetzt, habe mich in die SolidGS Community eingebracht und eingearbeitet und bin mittlerweile ein Bestandteil mit meiner Library.
Was hast du für eine Library gemacht?
Ich habe eine Library, die nennt sich Modular Forms.
Formular Problem.
Genau. Ist im Grunde eine Bibliothek für die Handhabung und Validierung von Formularen. Das heißt Modular Forms kümmert sich die Business Logik eines Formulars und liefert den Chleun und Entwicklerinnen im Grunde den Data Layer, den man dann benutzen kann, die UI anzuzeigen. Das heißt, jemand, der Modular Forms nutzt, muss im Grunde nur noch ein Formular erstellen und dann die Data Data Layers nutzen, also bei uns zum Beispiel eine field Komponente und kann dann da wieder kleine Validierung Funktionen übergeben und kann im Grunde von oben nach unten super übersichtlich ein Formular aufbauen, alles was dann im Hintergrund passieren muss, dass so ein Formular validiert wird, dass die Fehlermeldungen richtig ausgegeben werden, dass Felder, die halt Fehler enthalten, automatisch fokussiert werden. Und all das kümmert sich Material Forms. Und man kann da ganz, ganz einfache Formulare bauen und auch super komplexe, die dynamisch sind und wo man neue Felder hinzufügen kann und so weiter. Aber das sprengt vermutlich.
Das packen wir auf jeden Fall mal in die Shownotes. Das klingt auf jeden Fall cool. Ich meine, Sebi.
Du guckst gerade. Sorry, das ist ein Paket fürSolid.
Genau. Das ist im Grunde baut nativ auf solid. Js auf. Das heißt, ich nutze unter der Haube die solid. Js Signals für State und alles, was halt solid mit sich bringt.
Okay, und jetzt hast du die Plattform auch mit Solid gebaut?
Genau in dem Fall sogar mit Solid Start. Also Solid Start auf Deutsch. Was ist das? Das ist das Metaframework, an dem Ryan und Nikil, der auch im Co-Team ist, grad arbeiten. Also das ist sowas wie Next Shares for Solid, aber mit ein paar neuen Ideen und auch mit vielen Dingen, die man in der Vergangenheit aus anderen Frameworks gelernt hat. Also zum Beispiel findet man viel von Remix wieder und Rein und das Team ist auch im Austausch mit den ganzen anderen Entwicklern und Entwicklerinnen, die zum Beispiel auch in Quick arbeiten. Ja, die versuchen gerade so das Beste, was man so kennt, zusammenzuführen.
Ja, aber cool, dann zumindest... Erstens haben wir jetzt mal verstanden, ganz high level, was ist denn ein solid, wo reiht es sich ein und über was unterhalten wir uns überhaupt, wie du dazu kamst? Und vielleicht, damit man es mal so ein bisschen vergleichen kann, es wirkt ja wie ein sehr oder hast du ja gesagt, relativ neues Framework 2018 Open Source. Vielleicht können wir erst mal so ein bisschen das Feature Set vergleichen. So ist es wirklich. Also klar, klingt jetzt irgendwie nach einer geileren Reaktivität, klingt nach irgendwie ohne Virtual Dom alles schneller so, aber kann ich damit auch genauso große Applikationen bauen wie mit den Rest der Frameworks? Was bringt Solid so mit? Ist das State of the Art vergleichbar mit den anderen Frameworks?
Ja, wir können vielleicht einfach mal kurz die Liste, die ich vor mir habe, so ein bisschen abgehen. Also wie gerade schon gesagt, SolidGS bietet Reaktivität ohne virtuelles Dom und bietet damit auch eine direkte Reaktivität. Zum Beispiel jetzt bei React ist es, wenn man es genau nimmt, nicht direkt, weil eine Änderung führt dazu, dass im Grunde die App neu gerendert wird. Dann werden die VIDOMs, auf das gehen wir gleich auch noch ein, verglichen und dann daraufhin werden die Unterschiede halt aus oder werden, die Unterschiede führen dann halt zu Änderungen. Und bei Solid führt eine Änderung des Zustands zu einer direkten Änderung zum Beispiel am Dom. Das heißt, wir haben diese fein Granular Reaktivität mit der extremen Performance, die da einhergeht. Wie schon gesagt, führt Solid einige der Performance Benchmarks an. Man muss aber auch dazu sagen, es gibt mittlerweile auch dann doch wieder wie VIDAM Library, die da ganz gut mithalten und ich glaube sogar in manchen Dingen gleich schnell oder vielleicht sogar schneller sind. Da zählt sowas wie „Club Millionens. Js hinzu, aber da kenne ich mich jetzt nicht weiter aus. Was auch cool ist bei „Solid, durch die Signals können Dependencys, also Abhängigkeiten, automatisch getrackt werden.
Bei React, also die wo React nutzen, die kennen das. Bei UseEffect haben wir diesen Dependenc Array, wo wir halt React sagen, wenn sich eins von diesen Abhängigkeiten verändert, dann führ mal bitte mein „Effect neu aus. Und das fällt alles raus, weil „Solid kann selber erkennen, was konsumiert wird. Das schauen wir auch gleich uns noch genauer an. Deshalb ist es gar nicht erforderlich, da überhaupt einen Abhängigkeits Array zu erstellen, plus es macht auch noch mal die Performance besser. Zum Beispiel bei React, wenn sich irgendwas der Abhängigkeiten ändert, dann muss der Effekt nur ausgeführt werden. Und wenn ich jetzt aber ein If Statement habe, das sagt if a and b und sich zum Beispiel nur das eine, also zum Beispiel b ändert, aber a schon falsch war und sich dann aber b verändert, aber gleichgeblieben ist, dann ändert sich ja nichts an dem, was da passiert. Aber es muss trotzdem ausgeführt werden. Bei Solid ist es nicht so, weil wenn wir jetzt zum Beispiel in einem Effekt ein If Statement haben und da wird als erstes gefragt if a und wenn das schon falsch ist, dann wird ja der andere Code erst gar nicht ausgeführt. Das heißt erst dann, wenn sich a ändert und dann erst es erforderlich wird, dass man zum Beispiel auch b kennt, dann werden halt die anderen Abhängigkeiten getrackt und dadurch ist es dann auch noch mal ein bisschen performanter.
Und vielleicht noch kurz ein paar Hardfacts. Solid. Js sieht erst mal recht ähnlich zu React aus. Man hat auch, wie man es halt kennt, seine Komponenten. Man hat JSX, all das und auch die API von Solid ist dann doch sehr ähnlich zu den React Hooks. Deshalb kommt es einem auch irgendwie sehr bekannt vor. Dann hat Solid auch ein verhältnismäßig kleinen Bundle mit 7 bis 8 kb. React steht ja bei ungefähr 40 mit der Dom Library. Dann nutzt Solid. Js für das Build Tool Weed, was vermutlich auch viele cool finden. Und aktuell steht Solid bei knapp 27000 Sterne bei GitHub und knapp 100000 wöchentlichen Downloads bei npm.
Cool. Mich interessiert, wie es sich zu Swellt abgrenzt, weil der Swellt hat ja so einen ähnlichen Ansatz.
Ja, wenn man es sich im Detail anschaut, ist Solid komplett anders wie Swellt. Dazu muss ich aber sagen, ich bin nicht so in Deep in Swellt. Was ich aus den Talks von z. B. Ryan weiß, ist, dass Swellt natürlich den eigenen Code nimmt und den komplett durch den Compiler verändert und dann JavaScript Code generiert, der auch direkt Änderungen vornimmt. Aber unter der Haube, glaube ich, funktioniert es dann ähnlicher wie React und ist dann doch ganz anders wie wie Soll. Wobei, Swelt nutzt ja auch kein VIDOM. Also da tue ich mir ehrlich gesagt schwer, weil ich zu wenig in Swellet drin bin.
Das erste, was ich bei Soll. Js gelesen habe, war ja auch dieser, gerade was irgendwie auch im Kompilier-Schritt ja viel, also da dachte ich, dass es relativ ähnlich zu Swellt wäre mit diesem Kompilier-Schritt, dass ja da der Output, also im Kompilier-Schritt schon sehr viel von der Reaktivität einfach dort direkt gemacht wird und gar nicht so viel die Library später einbindet, dann.
Im Browser. Dieser Kompilier-Schritt ist wirklich komplett anders wie bei Swellt. Bei Swellt wird ja die ganze App kompiliert. Das heißt, ich kann schreiben let und dann eine Variable und dann kann ich die irgendwo verändern und dann kann der Compiler das nachvollziehen und kann diesen Code reaktiv machen. Bei „Solid. Js wird der Compile-Schritt nur auf den JSEX-Code angewendet. Das heißt, der grundlegende Code der Komponente bleibt gleich. Und im Grunde passiert da auch nicht groß eine Magic, sondern diese JSEX-Elemente werden einfach umgewandelt zu JavaScript-Funktionen, die dann wiederum Dom-Elemente generieren, also ganz normal mit der nativen Browser API und dann diese zurückgeben.
Das heißt aber der Kompilierstelle, also bei das, was dann die Magic macht, dass wirklich so nur punktuelle Nodes in meiner Seite am Ende gererendert werden können, wenn sich irgendwas verändert. Also das brauchst du wahrscheinlich dafür, dass du meinst, ich kann nur, wenn ich mein Formularfeld irgendwie in String finde, wird nur dieses eine Feld im Formular gererendert und nicht die gesamte Seite.
Genau, das ist ein wichtiger Teil auch von der fein Granularen Reaktivität. Wobei man aber dazu sagen muss, Swellt ist z. B. Angewiesen auf den Compile Schritt, ohne das funktioniert Swellt nicht. Solid kann auch direkt im Browser verwendet werden, weil es gibt unterschiedliche Wege, wie man letztendlich das JCX rendert. Den Weg, den Solid standardmäßig benutzt mit dem Compile Schritt, ist natürlich der performanteste. Aber es gibt auch noch zwei weitere Wege. Einmal über die H-Funktion, das kennt man vielleicht, also die Leute, wo ein bisschen in Dieb drin sind, wissen, was ich meine. Und dann gibt es auch noch die Render-Möglichkeit über so eine Art Template Literal. Also da bin ich nicht ganz drin, aber es geht auf jeden Fall, dass man SOLLET direkt über CDN irgendwie bezieht und dann auch direkt in einem HTML-Element ausführt ohne diesen Koppelschritt drumherum.
Und auch dann weißt du, ob ich dann trotzdem diese feingranulare.
Reaktivität habe, oder? Ja, aber nicht ganz so detailliert, soweit ich weiß.
Ich glaube, zu meinem Verständnis, du hast ja vorhin viele Punkte von dieser feingranularen Reaktivität gesprochen. Ich glaube, es würde vielleicht Sinn machen, an der Stelle mal zu verstehen, wie Swellt das jetzt genau macht mit dieser feingranularen Reaktivität oder wie.
Die Reaktivität... Du meint Swellt?
Nein, Swellt. Nein, es wurde zu überzeugen. Ich will dich wegbringen von dem Framework. Du hast ja vorhin schlecht über View geredet. Ich überzeugt dich noch von irgendwas anderem. Ja, ich meine es wählt. Genau. Es ist Freitag. Ja, ich meine es soll. Das tut mir leid.
Ja, also wir können jetzt mal den nächsten Punkt angehen und können mal so ein bisschen uns anschauen. Wie funktioniert denn diese Reaktivität ohne diesen Video? Also nahezu jede größere Library nutzt aktuell einen VIDOM. Wir haben React, wir haben View. Genau die benutzen den VIDOM alles so ein bisschen unterschiedlich. Aber vielleicht noch mal ganz kurz dazu. Was ist denn überhaupt ein VIDOM? Ein VIDOM ist im Grunde ein virtuelles Abbild von dem Dom, das man aktuell im Browser sieht. Dom steht dabei für Dokument, Objekt, Model und ist am Ende so gesehen ein großes Objekt oder eine Baumstruktur, wo sich halt die Dom, Nodes und Elemente drin befinden. Und ein wie Dom baut das im Grunde nach. Warum macht es einen wie Dom oder warum macht es Sinn einen wie Dom zu benutzen und nicht direkt irgendwie dauernd den Dom komplett zu überschreiben oder so? Der Dom am Dom hängt natürlich viel. Also die ganzen Listener oder auch allein schon, dass die UI aktualisiert werden muss und gezeichnet werden muss. Das heißt, wenn sich was im Dom verändert, dann benötigt es Leistung von eurem Rechner. Und deshalb baut man erst einen VIDOM und dann kann man den neuen VIDOM, also vielleicht noch mal ganz zurück, wie funktioniert so was wie React oder auch View?
Wenn sich bei React der Zustand verändert, dann wird einfach eine Komponente und auch die Kinder darunter neu ausgeführt. Das heißt, die ganze Funktion wird im Grunde noch mal neu ausgeführt. Das heißt, wenn man eine ganze React App ausführt, die ganzen Komponenten, was am Ende nur Funktionen sind, dann erhält man am Ende ein virtuelles Abbild von dem, was gezeichnet werden muss. Und dieses VIDOM kann man dann mit dem zuvor erstellten Wie-Dom vergleichen. Und daran kann man dann erkennen, was hat sich denn jetzt wirklich verändert und kann dann diese Änderung gezielt am richtigen Dom vornehmen. Und das macht den ganzen Schritt halt einfach performanter. React rendert zum Beispiel die komplette Komponente neu, führt den Template Part und Solid macht das überhaupt nicht. Und das funktioniert deshalb, weil die J, also erst mal haben wir das System mit den Signals, auf das wir auch noch gleich genau reingehen, eingehen, mit den Gettern und Settern. Das heißt, wenn bei Solid State konsumiert wird, dann passiert es über einen Getter und der Getter kann dann eine Subscription auf den aktuellen Kontext von dem Code, der das Signal konsumiert, Subscriben. Und immer dann, wenn sich dann der Zustand ändert, kann der Kontext neu ausgeführt werden, was dann halt zu einer Aktualisierung führt.
Und jetzt das Besondere, was wir gerade auch schon so ein bisschen angesprochen haben, mit dem Compile-Schritt ist der, dass wenn wir jetzt, also jeder, der vielleicht gerade doch irgendwie ein Handy oder besser einen Laptop zur Hand hat, der kann vielleicht mal auf solid. Js gehen und dort in der Navigation auf den Playground klicken.
Bist du bei Solid.
Oder bei Swelt?
Ach, Solid.
Ach sorry. Bist du Playground?
Ja, dann ja, von Swelt. Von Solid.
Ja, von Solid. Ja, von Swelt. Ja, von Solid. Ja, von Swelt.
Von Solid. Ja, von Swelt bin ich ja. Oh ne, wir gucken über die Schulter.
Da hat man ja standardmäßig das Beispiel mit dem Counter. Also ganz normaler Code, wie man es auch zum Beispiel von React kennt.
Ich sehe hier einen Button, der eine Zahl hochzählt.
Wenn ich darauf klicke. Und wenn man jetzt rechts das Result sieht, kann man das Ganze auch ausführen. Aber viel interessanter ist, wenn wir auf den Output klicken.
Ich habe geklickt.
So, was macht nämlich jetzt der Compile-Schritt bei Solid? Wir haben ja Links in unserem, also vielleicht noch mal zum Verständnis, dass auch jeder ohne Laptop das jetzt nachvollzieht. Sehen kann. Wir haben auf der linken Seite im Grunde im Code Editor eine Komponente, die nennt sich Counter, hat im Grunde einen State, das eine Zahl ist und der kann über einen Button, der sich im JSEX-Bereich befindet, hoch gezählt werden. Und das heißt, wir haben jetzt JSEX, das am Ende einfach nur ein HTML-Button ist, der im Inhalt die aktuelle Zahl hat und im On-Click-Event die Zahl erhöht. Und was jetzt der Compile-Schritt macht, der extrahiert den statischen Teil von diesem JSEX-Code. Das sieht man im Output jetzt bei mir oben in Zeile … Warte, ich muss kurz erst mal zwischen. Genau in Zeile 5.
Da haben wir irgendein Template String, wo einfach nur drinsteht Button Typ Button.
Genau alles, was irgendwie statisch an dieser, an diesem HTML Element ist, befindet sich in diesem Template String drin. Hat den Vorteil, dass dieser Template String super effizient geklont werden kann. Und was dann jetzt halt passiert unter der Haube ist dieser JSEX Code wird umgewandelt in eine JavaScript Funktion, die wiederum ein echtes Dom Node erzeugt. Und wenn jetzt in dem, also in diesem JSEX Code sich State befindet, dann wird dieser State nochmal geschachtelt, im Grunde in einem Effekt, das nennt sich jetzt hier $insert. Und dieser Code wiederum baut dann den Wert des States in den Dom, in das Dom Element ein und gibt dann am Ende das ganze Dom Element zurück. Bedeutet, wir haben jetzt eine Funktion, die gezielt DOM-Operationen durchführt. Und wenn sich jetzt der Zustand verändert, dann kann ganz gezielt in dem Fall diese $insert-Funktion aufgerufen werden, die dann ganz gezielt am DOM-Element auch nur das verändert, was verändert werden muss. Und die Feingranularität geht bis auf die einzelnen Text-Notes herunter. Das heißt, wenn sich da Text in einem HTML-Element befindet, dann muss nicht das ganze HTML-Element erneuert werden, sondern nur dieses Text-Note im HTML-Element, das tatsächlich von der Änderung betroffen ist. Und viel Granularer geht es eigentlich nicht mehr.
Das heißt, wenn man das selber mit Vanilla JavaScript schreibt, würde man vermutlich auch so ungefähr vorgehen, wenn man die bestmöglichste Performance erzielen möchte.
Interessant. Ich meine, hier sieht man ja wirklich genau das, was du sagst. Am Ende der Compile-Schritt hier wirklich nur in dem JSEX, in dem Return Statement irgendwie ist und der Rest ist ja komplett gleich. Das, was du meinst, ist vorhin die API, auf die wir auch gleich noch mal eingehen mit dem Create Signal und so, ist ja alles wirklich komplett gleich geblieben, echt nur in dem JSExpo. Das klingt auf jeden Fall interessant aus. Finde ich ein guter Punkt, da mal reinzuschauen in diesen Output. Ich glaube, dann versteht man es ein bisschen, wenn man noch gleich versteht, wie Signals und Defacts so funktionieren, also wie die Reaktivität dann da auch funktioniert. Das ist ja, glaube ich, gerade schon mal kurz angesprochen mit dem Kontext und so, auf den sich Subscribe wird, aber ich glaube, dem macht es Sinn gleich auch noch mal zu verstehen.
Ja, vielleicht ist das auch, wäre das interessant als nächstes, uns mal anzuschauen. Ja, gerne. Und zwar ein Buzzword, das mit Solid einhergeht, das sind die Signals. Vor allem, also wer vielleicht ein bisschen Loftfit aktiv ist, hat es in den letzten Wochen mitbekommen, dass da viel Trubel drumherum war, auch weil jetzt immer mehr andere Libraries anfangen, ihr Stat mit Signals zu implementieren. Wir sehen das jetzt zum Beispiel bei Projekt, die anfangen, auch eine Signal API anzubieten und jetzt ganz neu, ich glaube vor drei Wochen hat das angekündigt, auch Angular ist es gerade dabei, Signals mit einzubauen.
Und das ist aber wofür bauen sie es denn? Weil sie auch eine feingranulare Reaktivität damit wollen oder warum? Was ist das Ziel dafür? Vielleicht erklärst du gleich erst mal, wie die Signals funktionen, bevor wir uns darüber unterhalten, außer du hast direkt schon die Antwort.
Bei Angular weiß ich tatsächlich nicht so genau, warum die es machen.
Ja, dann lass uns doch mal eingehen auf diese Signal-API.
Aber ich denke, am Ende hat es wahrscheinlich schon immer irgendwas ein bisschen mit Performance zu tun. Besprechen wir vielleicht einmal ganz kurz, was ist denn überhaupt ein Signal? Ganz einfach gesagt, ein Signal ist erst mal nur eine API zum Abrufen und Aktualisieren von einem Zustand. Ein Signal ist erst mal sehr, sehr ähnlich zu zum Beispiel der UseState Hook in React. Der Unterschied ist, die UseState Hook in React gibt zum einen den aktuellen Wert zurück und einen Setter. React verpackt es in einem Array, sodass man halt die Rückgabewerte benennen kann, so wie man möchte. Und der Unterschied bei einem Signal ist, ein Signal liefert nicht den Wert und den Setter zurück, sondern einen Getter und einen Setter. Das heißt React liefert einem nur den Wert zurück. React weiß aber dann nicht, was mit dem Wert passiert, wo der Wert eingesetzt wird. Durch diesen Getter weiß Solid ganz genau, in welchem Kontext wird der Wert denn letztendlich konsumiert? Und dadurch kann man im Grunde, kann eine Subscription auf dem Kontext gesetzt werden. Und wenn dann der Setter gecrawlt wird, können die ganzen Subscription ausgeführt werden, wodurch dann gezielt an der Stelle, wo auch eine Änderung erfolgen muss, auch eine Änderung erfolgen kann.
Das heißt, Subscription sind sozusagen alle, die irgendwo den Getter nutzen, die irgendwie Count haben wollen. Die sind dann Subscription, die dann von dem.
Setter gecrawlt wird. Genau. Unter der Haube, muss man dazu sagen, gehört dann noch mal viel, viel mehr dazu. Da gibt es unterschiedliche Modelle, die wo da drin sind, die wissen das, da gibt es Push Modelle, Pull Modelle, eine Mischung aus Push Pull. Das heißt, man kann das so programmieren, dass wenn sich der Zustand verändert, man direkt alle Kontexte neu ausführt, die den Zustand konsumieren. Man kann es aber auch anders implementieren, sodass diese Contexts sich den Zustand dann holen. Also da gibt es unterschiedliche Modelle. Was vielleicht da auch noch mal wichtig ist zu sagen bei SolidGS befindet sich der Getter und der Setter in zwei unterschiedlichen Funktionen. Es gibt aber auch Implementierungen. Ich glaube, so ist es bei View und zum Beispiel auch bei Quick. Da befindet sich der Getter und der Setter in einem Rückgabewert. View zum Beispiel bei der Rev API nutzt dann dort Value und dort Value wird in dem Fall wahrscheinlich eine Proxy Objekt sein, das dann einen Setter und einen Getter setzt. Und je nachdem, ob man halt dorte Value liest oder schreibt, kann dann noch mal gesondert Code ausgeführt werden. Aber die Grundidee ist am Ende dieselbe.
Okay, und eine Subscription, die Möglichkeiten mich zu Subscriben auf Count wären dann einerseits dieses UseEffect zu nutzen oder ich kann es im JSX schreiben? Oder gibt es noch andere Möglichkeiten, wo ich diesen Getter oder kann ich ihn überall, also wie, wie, was muss ich beachten, mich darauf.
Zu Subscriben? Man muss halt, man muss verstehen, dass man den Getter immer beim Endkonsumenten aufrufen muss. Und man muss dann halt auch das Kontext-Modell, das so ein bisschen verstehen. Also wie du schon gesagt hast, zum einen kann man das in einem CreateEffect nutzen. Man kann es in einer Create Memo, das werden wir bestimmt später auch noch kurz ansprechen nutzen oder dann halt im JSEX-Bereich. Und ein Punkt, der wichtig ist, den du oder der da auch so ein bisschen einhergeht, wenn ein Getter als Grundzustand als Probs einer Komponente übergeben wird, dann müssen wir ja verhindern, so gesehen, dass der da direkt ausgeführt wird. Allerdings wäre es auch irgendwie von der API und von der die X wahrscheinlich bescheuert, wenn wir jedes Mal immer nur den Getter in sich durchreichen, die Funktion. Und Solid hat eine coole Lösung. Das heißt, wenn wir so eine Komponente über Probs übergeben und ihn dort direkt drin ausführen, dann schachtelt Solid im Compile-Schritt das in einem Getter. Das war jetzt wahrscheinlich verwirrend, weil so häufig das Wort Getter aufkam. Aber bei einem JavaScript-Objekt kann man ja schreiben, man kann aber auch sagen get Value, also dann den Namen von dem jeweiligen Key und dann macht man da eine Funktion daraus.
Und wenn man dann z. B. Objekt. Value abruft, wird am Ende dieser Getter ausgeführt. Und Solid startet dann im Compile-Schritt das in so einen Getter. Was bedeutet, wenn ich das jetzt durch Prop-Trilling, also durch ganz viele Komponenten durchreiche, ich und dann irgendwo ganz am Ende im JSEX-Code es dann auch wirklich in einem Button-Element oder was auch immer ausgeführt wird, dann werden rücklaufend die ganzen Getter ausgeführt, bis dann am Ende so gesehen der Getter des Signals ausgeführt wird. Und dadurch befindet sich aber dann die Ausführung des Signals letztendlich wieder im richtigen Kontext, das heißt zum Beispiel in einem Button Element oder so.
Das heißt aber, wenn wir jetzt mal das Beispiel machen, ich bin eine Unterkomponente, wir hatten ja vorhin das Counter Beispiel und irgendwie wir haben ein Signal, was im Endeffekt eine Zahl ist, irgendwie eine int, dann kriege ich in meiner Prop wirklich sehe ich in der, du kannst gleich noch darüber unterhalten, kann ich eigentlich TypeScript nutzen? Haben wir noch gar nicht darüber gesprochen? Ja, kann man. Okay, sehe ich. Okay, ist eine ist eine Number. Das heißt auch in meinem JSX muss ich normalerweise, wenn ich dann so ein Create Signal habe, muss ich ja wirklich den Getter ausführen, ihn im JSX zu bekommen. Aber wenn ich es über eine Prop bekomme, dann schreibe ich da einfach nur.
Hin: Count. Da führe ich es auch aus. Genau.
Da führe ich es auch aus. Also ich muss... Ist es generell, weil ich jede Prop ausführen muss oder ist es dann … Wie ist die Definition von meinen Prop? Steht da dann Count Number oder steht da dann eine Function in Number Return oder wie ist die Typendefinition von diesem Counter, der.
Mir übergeht? Das ist so gerade die Besonderheit, auf die ich ein bisschen hinaus wollte. Das heißt, wenn wir jetzt Count ausführen, also wirklich den Getter ausführen in einer Probs, die wir eine Komponente übergeben, dann wird dieser Aufruf, also am Ende ist ja Probs einfach ein JavaScript Objekt, das als erster Parameter an eine Funktion übergeben wird. Und statt das jetzt in dieser in diesem Objekt, sag mal der Wert Count direkt im Key Count als Wert übergeben wird, schreibt Soll er das in ein Getter, das heißt get_ Count und dann Funktion return Count, also dann den Getter des Signals. Und dadurch füge ich dann halt am Ende, wenn ich auf probs. Count zugreife, diesen Getter auf, der wiederum den Getter des.
Signals ausführt. Wenn ich sie aber in meinem js nutze, die Unterkomponente, schreibe ich einfach probs. Count und ich schreibe nicht Count, wie ich schreiben würde, wenn es ein Signal wäre, der in meinem.
Scope definiert ist. Genau, ich muss es dann nicht aufrufen.
Okay, das wollte ich. Genau damit das beantwortet.
Genau meine Frage. Und das bringt gleich etwas weiteres mit sich, was man wissen muss. Dieser Zugriff auf Probs. Count führt ja am Ende dann in Getter aus. Bedeutet, wir dürfen kein Probs Destructuring anwenden. Wir dürfen die Probs, also das Probs Objekt nicht destrukturieren, was ja in React üblich ist, weil dort erfolgt ja dann an der Stelle bereits der Zugriff über den Getter und das darf ja eben nicht passieren. Der Zugriff soll ja erst zum Beispiel im JSEX Code dann wieder erfolgen, wo wir den dann irgendwie in den Text oder so einbauen. Und das ist zum Beispiel eine Regel, die man halt beachten muss.
Das ist ja auch ein typisches Probs-to-Refs, also gut, man kann es to-Refs ausführen, da wird man es ja destruktoren und so was. Ich habe auch keine Heldbarfunktionen, die mir irgendwie das Destructuring, also bei View hatten wir dieses to-Refs, dakann ich es nicht einfach JavaScript destrukturen.
Also was es gibt, es gibt eine Hilfsfunktion, Probs zu splitten, wenn man das braucht. Und ich glaube, es gibt auch wahrscheinlich einen Bubble Plugin oder irgendwas, wo man Objekt destrukturellStructuring anwenden kann und das wird einfach wieder umgeschrieben.
Aber es ist ja eher untypisch, dass man es macht. Man hält sich eher eigentlich.
So an.
Die Probs-Objekte und dann.
Getastet zu lassen. Zumindest ist es aktuell so Best Practice. Also man lässt einfach das Destructuring Rack weg und ich finde es auch gar nicht so verkehrt, weil dann weiß man halt immer von wo auch das halt einen Wert aus den.
Probs stammt. Wir haben ja jetzt schon häufiger über Komponenten gesprochen. Macht es an der Stelle mal Sinn zu erklären, wie so eine Komponente eigentlich genau aussieht, wie ich so eine Komponente definiere in solid.
Ja, also am Ende ist eine Komponente einfach eine JavaScript Funktion, die am Ende JSX zurückgibt. Die Leute, die React nutzen, die kennen das. Das ist im Grunde erstmal optisch gesehen, genau gleich. Es gibt aber ein paar Regeln, weil die Komponenten ganz anders funktionieren als in React. Komponenten in solid sind im Grunde einfach nur eine Setup Funktion. Das heißt, wenn eine Komponente eingebaut wird in die App, dann wird die nur einmal ausgeführt. Bei React wird sie ja jedes Mal erneut ausgeführt, wenn sich der Zustand ändert. Eine Solid. Js Komponente wird immer nur einmal ausgeführt. Das heißt, der Code läuft von oben nach unten ganz normal ab. Dabei kann man dann auch Effekte platzieren und so weiter, State deklarieren. Und am Ende gibt man dann den JSEX Code zurück und durch die feingranulare Reaktivität ist es ja dann gar nicht erst erforderlich, überhaupt die Komponente noch einmal neu auszuführen. Und das wiederum bringt auch ein paar Dinge mit sich mit, die man wissen muss. Da bei React die Komponente jedes Mal neu ausgeführt wird, kann ich ja einfach schreiben if, dann ein Statement, dann führt den JsonX Code aus und wenn das irgendwie nicht zutrifft, dann führt den JsonX Code aus.
Das heißt, ich kann in React mehrere Return Statements schreiben. Da aber in Solid die Komponente ja nur einmal ausgeführt wird, darf es auch nur ein Return Statement geben. Das heißt, wenn ich jetzt Control Flow brauche, also je nach Zustand irgendwas anders trendere, dann muss ich das direkt in diesem Return Statement im JSEX Code machen. Und deshalb liefert Solid auch eigene Komponenten mit, die das dann noch mal vereinfachen, also Komponenten wie zum Beispiel for für einen for loop oder auch show für ein if Statement, das halt nur dann was anzeigt, wenn eine Bedingung gegeben ist. Oder es gibt auch Control Flow Komponenten für Switch und Match. Also das ist so ein bisschen Switch.
Case mäßig. Gibt es so Slots oder irgendwie sowas? Oder wie übergebe ich jetzt und definiere ich eine Property da drin, importiere ich dann mir was aus der Runtime? Ich weiß nicht.
Solution nutzt keine Slots, sondern das funktioniert genau wie in React. Da werden einfach die Kinder direkt gerendert. Also das funktioniert so, dass man am Ende Probs kinderen nutzt. Also und das dann, wiedergibt im JSEX-Code.
Das übergebe ich einfach einen Slot übergebe ich als Property und nicht als Slot.
Ja, also wenn ich jetzt eine Komponente habe, kann ich entweder auch wieder andere Komponenten oder JSEX Code als Property übergeben, also über die Probs, oder dann halt im Inhalt der Komponente, also zwischen dem öffnenden und schließenden Tag. Und das ist dann gleichgestellt, als würde ich das der Childrant Prob übergeben.
Und weil du jetzt irgendwie, ich meine, das hast du ja schon ein bisschen Erfahrung mit React und im Vergleich zu dieses Konzept der Komponenten und dass ich immer nur ein Return Statement habe, so ist es irgendwie, hast du das Gefühl, dass das in irgendeiner Form limitierend ist? Oder ist es erfrischend simpel? Es ist aber gerade bei größeren. Ich meine, wenn man es erst mal sieht, wenn du darüber sprichst, das klingt nach einem coolen Ansatz, gerade in größeren Applikationen. Du baust jetzt deine E-Learning Plattform.
Ja, also ich denke, wenn man von React kommt, ist es dann doch irgendwie erst mal ein bisschen eine Umstellung, weil einfach ein paar Sachen, vor allem was die Komponenten angeht, anders funktionieren. Aber es bringt auch wieder verschiedene Vorteile mit sich, weil man nicht in sogenannte PID Faults laufen kann wie bei React. Also in React kann es sehr schnell mal passieren, dass man vielleicht in der Entwicklung in einen Bezug läuft, weil man zum Beispiel einen Intervall erstellt, der State verändert, dann aber vergisst, den Intervall wieder aufzuräumen, wenn die Komponente neu ausgeführt wird, was ja dafür dazu führen kann, dass wir exponentiell viele Intervalls irgendwann haben und es clasht dann im Grunde die App. Und da ja bei Solid die Komponente nur einmal ausgeführt wird, kann ich ja zum Beispiel auch Set Intervall einfach direkt in dem Komponenten Code ausführen und da kann nichts passieren.
Und wie ist das bei einer Child Komponente, die in einem for loop dann auch wieder weggeworfen wird? Da muss ich mich trotzdem ums Cleanen abkümmern, oder?
Was genau meinst du?
Wenn ich eine Child Komponente habe, ein Listen Element und das Element ist jetzt nicht mehr in der Liste drin, dann geht die Komponente ja weg, aber hat jetzt den Intervall gesetzt.
Genau dafür gibt es dann auch eine Clean up Funktion.
Also ein bisschen nachdenken muss ich trotzdem noch.
Also Clean up Funktion ist aber ein Lifecycle, da natürlich die Clean up Funktion rufe ich in der Chilke Komponente selbst sozusagen On.
Clean up. Genau die nennt sich bei Solid, glaube ich, genau On Clean up. Also was man sagen muss oder was vielleicht noch wichtig ist als Hinweis React hat ja die Hooks oder ich glaube im View nennt man die ja auch Hooks, oder?
Die LifeCycle Hooks jetzt oder welche?
Also einfach die Namensgebung. Bei React sagt man Hooks dazu, bei Solid nennt sich das Primitis. Und neben diesen Zustands-Primitus, Create Signal und dann createEffect for SideEffect und Create Memo und so weiter gibt es auch LifeCycle Funktion.
Das kann ich bei den Views einfach, für die Composible API und LifeCycle Hooks würde ich glaube ich ein View dazu sagen. So diese API warst du dann, wie war es in solid?
Primitiv.
Primitiv, okay. Genau. Ja, ich glaube, so wäre es in View die Nomenklatur.
Ja, und da gibt es dann halt auch LifeCycle Funktionen wie OnMount, OnCreener, wo man genau solche Sachen machen kann.
Aber wahrscheinlich nichts besonderes. Wahrscheinlich wie da das wahrscheinlich wie alle anderen auch die Lifecycle-Events.
Ja, also wie gesagt, das Feature Set, also das grundlegende Feature Set ist im Grunde gleich wie bei den ganzen anderen Frameworks. Aber wie man es dann letztendlich anwendet und wie es halt unter der Haube funktioniert, ist sehr verschieden. Was zum Beispiel super cool ist bei Solid, wenn ich State oder auch die Hooks bei React nutze oder auch so was wie Rev bei View, dann unterliegt es bestimmten Regeln. Also in React kann ich zum Beispiel eine Hook, die darf sich nicht in der if-Bedingung befinden. Die muss, wenn sich die Komponente, wenn die Komponente ausgeführt wird, immer an der gleichen Stelle in Anführungsstrichen befinden. Das heißt am Ende immer auf dem Root Level. Das heißt, ich kann nicht sagen if und dann halt ein Statement das, dann will ich.
Die.
Hook nutzen und ansonsten die, weil dann werden die Hooks in einer unterschiedlichen Reihenfolge aufgerufen, was dann React am Ende kaputt macht. Weil React muss ja wissen, wann an welcher Stelle ein State aufgerufen wurde, dann jedes Mal auch den richtigen State-Wert zurück zu liefern. Das heißt, es gibt einfach Regeln, die man beachten muss. Und diese ganzen Regeln, die entfallen komplett bei Solid. Das muss man überhaupt nicht beachten. Ein super Beispiel ist in React, wenn ich UseState nutze, dann kann ich das ja nur in der Komponente nutzen. Ich kann das nicht irgendwie in den Outer Scope legen. Wenn ich das mache, dann passiert ja nichts mehr, weil das ja nicht nur ausgeführt wird. Bei Solid ist es ganz egal, wenn ich zum Beispiel globalen State haben wollen würde und jetzt nicht, sage ich mal, über den normalen Weg über die Context API oder so gehe, könnte ich auch einfach einen Create Signal Aufruf außerhalb der Komponente machen und dann kann im Grunde der Getter und Setter von mehreren Komponenten genutzt werden und dann ist es im Grunde wie halt globaler State.
Kann man einfach so einen simplen Store damit eigentlich schon bauen, weil ich irgendwie meinen globalen Stake irgendwo halten kann? Ist ja auch durchaus was, was wir aus View so kennen und mit der Composible API öfter mal machen.
Die Lifecycle Primatives muss ich aber trotzdem auf oberster Ebene registrieren.
Das ist auch das Coole. Also wir haben zum Beispiel die Lifecycle Funktion On Clean Up. Die kann ich entweder in einer Komponente nutzen, irgendwas aufzuräumen, oder ich kann die auch einfach innerhalb von dem createEffect Aufruf nutzen, den Effekt aufzuräumen. Das heißt, die OnCreenUp richtet sich dann immer an den Kontext, in dem sie sich befindet.
Okay, aber dann muss ich sie in der Komponente, wenn ich sie für die Komponente verwenden will, da richtig verwenden. Da kann ich sie dann.
Nicht verschachteln. Genau geht ja auch nicht, weil die Komponente wird ja nicht neu ausgeführt. Also du kannst es schon verschachteln, aber ich weiß nicht, inwiefern das Sinn macht, weil die Komponente wird ja nie neu ausgeführt.
Ich glaube, den Part habe ich jetzt noch nicht ganz verstanden. Das heißt, ich kann einen Create Effekt definieren, den vielleicht irgendwo global definieren und darin auch schreiben on Clean Up. Und dann könnte ich … Was mache ich mit dem?
Hört sich an wie LifeCycle Events für diesen Effekt Scope, den es ja auch in Viewgap gibt.
Genau. Also ich habe es gerade bei View gar nicht mehr so im Kopf. Tut mir fast leid, weil das könnt ihr besser nachvollziehen. Jetzt bei React habe ich ja die Use Effekt Token. Und wenn ich einen Return Statement schreibe in die UseEffectHook, also in die Funktion, die ich an die UseEffectHook übergebe, dann kann ich da als Rückgabewert wiederum eine Funktion übergeben und die wird dann zum CleanUp ausgeführt. Und bei Solid würde man das dann halt so machen. Man schreibt createEffect, packt da als ersten Parameter seine Funktion, also seinen Effekt rein und kann dann innerhalb von seiner Funktion einfach dann die OnCreenUp Funktion aufrufen.
Und aber wenn ich dann, ich willglaube ich, aber ich glaube, ich habe es auch in View nicht so wirklich nutze. Ich wüsste nicht, wann dieser, wenn ich es global definiere, wann ist denn dann On Clean Up? Kann ich den Effekt dann in verschiedenen Komponenten nutzen? Und es wird jedes Mal aufgerufen, wenn diese Komponente oder wann, was heißt On.
Clean Up? Wenn du also On Clean Up bei einer Komponente heißt, wenn eine Komponente angemountet wird, also entfernt wird.
Genau, aber wenn ich jetzt Create Effekt global mache, ich habe es ja nicht in einer Komponente definiert.
Ach nein, global macht man On Clean Up nicht, macht ja keinen Sinn. Also du machst es immer in einem Kontext.
Ich dachte, wenn ich Create Effekt innerhalb nichtAlso ich könnte CreateEffect auch global machen und da OnCreenUp schreiben.
Genau. Also OnCreenUp wird dann immer dann ausgeführt, bevor das nächste Mal der Effekt ausgeführt wird. Und das kann man sich zunutze machen, wenn man zum Beispiel einen Timeout setzt, der nach einer verzögerten Zeit einen State verändert. Und wenn aber inzwischen Zeit sich irgendwas verändert hat und ich den Timeout neu setzen will und den alten nicht mehr ausführen will, kann ich in der onCreenUp-Funktion den alten Timeout aufräumen.
Das heißt On-Creen-Up in Komponente ist Komponente wird Unmonted, On-Creen-Up in CreateEffect wäre, der Effekt wird.
Neu ausgeführt. Genau. Das heißt, bevor der Effekt neu ausgeführt wird, läuft die OnCreenUp Funktion.
Jetzt habt ihr mich auch. Jetzt sind wir schon in vielen... Wir sind ein bisschen abgebogen in Solid. Ich habe zumindest jetzt schon mal einen guten Überblick. Vielleicht, weil wir ja unwissend sind Fabian, ist es was, was gibt es denn noch so bei Solid, was man auf jeden Fall nennen sollte?
Vielleicht gehen wir kurz noch mal auf die Reaktivity API ein, auf die Core Primitis. Und dem zu könnten wir vielleicht auch mal kurz besprechen, wie denn diese Reaktivität mit Effekts und Signal so in Deep funktioniert. Starten wir erst mal mit der API für die Übersicht. Für mich die zwei Haupt Primatives sind einmal Create Signal, ein Signal zu erstellen und Create Effekt für SideEffects. Das heißt, Create Effekt kann im Grunde an allen Stellen dann genutzt werden, wo man irgendeine Operation ausführen möchte, die halt erneut jedes Mal ausgeführt werden soll, wenn sich ein Signal ändert. Das heißt, ich kann dann ein Signal in Create Effekt konsumieren und sobald sich dieses Signal ändert, wird dann dieser Effekt ausgeführt. Das ist ja im Grunde auch genau das Gleiche, was in diesem JSEX Code beim Kompilier-Schritt passiert. Wenn ich dort ein Signal nutze, umzum Beispiel den Textinhalt von einem HTML-Element zu setzen, dann wird so gesehen diese Funktion, die genau das Textelement setzt, in einen Effekt gerappt. Und jedes Mal, wenn dann das Signal ändert, wird dann einfach dieser kleine Teil ausgeführt und deshalb kann da feingranular dann auch die Änderung am Dom erfolgen. Das ist im Grunde das Hauptprinzip von dieser Reaktivität.
Und neben diesen zwei Haupt-Primitus gibt es dann noch Create Memo für berechnete Werte, die auf Signals basieren, die man dann cacht. Das heißt, wenn man die an mehreren Stellen benötigt, wird es immer nur einmal ausgeführt und dann gecacht an die anderen Konsumenten ausgeliefert. Man kennt es in React unter Use Memo und in View unter Computed.
Und das andere, also das CreateEffect wäre dann ja Watch von View. So hätte ich es auch eingeführt. Wir haben Ref.
Oh.
No, WatchEffect. Genau. Und bei React dann UseEffect. Okay. Genau. Und dann haben wir noch als viertes, als vierten Primative Create Resource. Und das ist im Grunde für alle asynchronen Operationen. Das heißt, wenn ich zum Beispiel Daten von der Datenbank fette, das heißt Create Resource liefert am Ende auch so gesehen ein Signal, kann aber mit asynchronen Aufrufen umgehen und liefert einem ein Objekt zurück, das auch den aktuellen Zustand der Operation widerspiegelt. Das heißt, man kann dann sagen Data. Loading oder so und kann dann halt irgendwas anderes anzeigen, bis es dann gefälscht wurde und kann dann die letztendlichen Daten in der UI anzeigen.
Das wird mir jetzt kein Beispiel von irgendeiner anderen Library dazu einfallen. Gibt es da was Vergleichbares? Also aus der View-Welt kenne ich dafür nichts.
Also nichts von Haus, was von Haus.
Aus dabei ist? Genau, auch React hat es so gesehen. Und deshalb sind ja so Libraries entstanden wie React Query.
Also hast du dafür jemals ein Library in View genutzt oder machen wir das immer alles händisch, was das angeht? Also ich.
Habe es bisher auch nicht vermisst. Ich weiß, dass es bei View, Use, Use, Async, Ref oder Use Async, Computed.
Oder so was gibt. Man kann ja auch diese Funktionalität, deshalb habe ich ja auch gesagt, die zwei Haupt-Primites sind Create Signal und Create Effekt, weil Create Resource kann ich ja selber mit Create Signal wiederum implementieren und mit Create Effekt in Kombination.
Aber der Vorteil ist dann, dass es so ein State gibt wie Loading.
Complicity, Error. Genau, die übernehmen einfach dann schon einen Teil der Implementation für ein plus es wird halt dann auch neu ausgeführt. Also man kann das dann so auch bauen, dass es neu ausgeführt wird, wenn sich irgendwie Zustand verändert. Das heißt, wenn man zum Beispiel in Create Resource eine Use ID konsumiert, von dem Nutzer das Profil abzurufen, dann kann ich das so implementieren, dass es einfach neu gefälscht wird, sobald sich die ID verändert.
Ja, cool. Core Primitiv, verstanden.
Und jetzt können wir vielleicht mal ein bisschen in die Tiefe reingehen, wie denn diese Reaktivität mit Setter, Gettern und Effekten funktioniert. Weil das zeigt SolidGS in dem 10 Minuten Video, das man auf der Startseite findet, schön übersichtlich in einem Video. Ich versuche es jetzt mal hier im Podcast … Der Podcast ohne Code zu sehen.
Ich habe es kurz angehalten, das Video, als Sie dann den Code dafür.
Gezeigt haben. Ja, musste ich auch, weil man muss erst mal nachdenken. Also im Grunde versuche ich jetzt einmal ganz kurz zu erklären, wie man selbst in etwa 30 Zeilen Create Signal und Create Effekt implementieren kann und damit in Anführungsstrichen schon die Kernfunktionalität von Solid hat. Natürlich passiert dann am Ende noch viel mehr darunter, das zu optimieren und zu verbessern. Aber wir schauen uns jetzt einfach mal an, wie das funktioniert, weil wenn man das einmal verstanden hat, dann versteht man auch, wie die Reaktivität bei Solid funktioniert und warum es diese Regeln gibt, die.
Es dann vielleicht gibt. Fand ich auch. Ich fand es auch cool, dass Sie das so erklärt haben.
Und zwar legen wir los. In der ersten Zeile erstellen wir eine Variable, das als Wert ein Array ist. Das kann man zum Beispiel nennen, ein Effekt-Stack. Und das ist am Ende ein Array, das nachher einfach nur Funktionen beinhaltet. Und das ist zu Beginn leer. Und als nächstes füge ich der Datei eine Funktion hinzu, die nennt sich createEffect. Und createEffect akzeptiert als ersten Parameter wiederum eine Funktion, sodass ich dann später, wenn ich createEffect nutze, createEffect aufrufe, dort meine Error Function übergebe und dann halt mein Code ausführe. Und was createEffect wiederum intern macht, es nimmt diesen ersten Parameter und Wrappt diesen innerhalb von createEffect wieder in eine Error Function. Das heißt, schreibt dann zum Beispiel const effect = Error Function. Und darin wird dann die eigentliche Aktion des Nutzers, also dieser erste Parameter, diese Funktion ausgeführt. Und was jetzt innerhalb dieser Funktion in der createEffect Funktion passiert, ist sie nimmt sich selbst und packt sich in diesen Effekt Stack. Das heißt, ich habe jetzt in createEffect wiederum eine Funktion, die sich selbst diesen Effekt Stack hinzufügt und dann die Aktion, also die den ersten Parameter ausführt und dann am Ende sich wieder aus dem Effekt Stack entfernt.
Und dann am Ende ruft createEffect dann halt diese Funktion, die innerhalb erstellt wurde, auch auf, dass das auch direkt initial ausgeführt wird. Also ich hoffe, es war einigermaßen verständlich. Also im Grunde muss man sich einfach nur merken, wenn ich jetzt CreateEffect nutze und da jetzt meine eigene Funktion übergebe, dann wird intern diese Funktion in eine Funktion gepackt, die bei Ausführung sich selbst an diesen Effekt Stack übergibt. Bedeutet immer der aktuellste Kontext ist immer ganz am Ende von diesem Effekt Stack. Und auf der anderen Seite geht es jetzt über in diese Signals. Ich erkläre vielleicht einmal ganz kurz, wenn ich nämlich jetzt in einem Effekt ein Signal nutze und den Getter aufruf, dann kann ich über den letzten Eintrag im Effekt Stack den aktuellen Kontext mir wiederum abrufen und kann den in eine Liste packen, also im Grunde eine Subscription List und kann dann über den Setter vom Signal einfach diese Liste neu ausführen, nachdem sich dann natürlich der Wert verändert hat. Und dadurch kann ich halt ganz gezielt immer die Kontexte neu ausführen, die den Zustand konsumieren.
Also wenn man, ohne den Code jetzt komplett zu verstehen, nur mal von der Signal Richtung ausgeht, wenn der Getter von meinem Signal ausgeführt wird, dann guckt er immer so: „Hey, von wem wurde ich denn gerade ausgeführt? Und packt das in eine Subscription-Liste. Das ist erstmal so das Core-Prinzip aus Signal-Richtung. Er kann irgendwie rausfinden, wer hat mich gerade aufgerufen und packt die in diese Subscription-Liste rein. Und damit weiß der Getter immer selbst: „Okay, von denen wurde ich allen schon mal ausgeführt. Wenn der Setter aufgerufen wird, guckt er in die Subscriber-Liste und sieht: „Es gibt drei Subscriber. Ich wurde neu ausgeführt, dann gib den Subscribern mal Bescheid. So das aus.
Signeln, richtig? Ganz, ganz einfach formuliert, ja. Weil unter der Haube muss man natürlich bedenken, dass sich ein Signal aus anderen Signals wieder zusammensetzen kann. Das heißt, ich kann ein Signal A haben und Signal B. Das zusammen gibt dann wieder ein Signal C und das wird dann wieder benutzt, irgendwie ein Signal C zu erstellen. Das heißt, Signals können ja aufeinander aufbauen. Und ich möchte ja dann, wenn sich Signal A ändert, wäre es natürlich optimal, zum Beispiel, dass ich erst dann mit A und B C berechne und dann mit dem Endresultat von C gemeinsam wieder D und nicht wenn sich A ändert direkt mit den aktuellen Wert von C zum Beispiel D wieder mache, sondern das halt in einer sinnvollen Reihenfolge mache. Und das ist genau die Komplexität, die dann Solid unter der Haube für einen löst.
Ja, wahrscheinlich die dann komplett zu verstehen, so ob man den Code sich dann nochmal.
Anschauen soll. Aber ja, da kann ich auch direkt einen Tipp geben. Der Autor von Solid, G. S. Ryan macht glaube ich meistens oder fast immer Freitag, zu unserer Zeit abends einen Stream, geht auch meistens fünf sechs Stunden und genau dort spricht er solche Themen wirklich in und geht da wirklich rein und holt sich dann meistens auch Leute dazu. Also es gibt Themen genau dazu und es gibt auch Themen, wo die wohl sich rein dann andere Frameworks anschaut und ganz genau versucht zu verstehen, wie dort Dinge passieren und was vielleicht cool daran ist oder vielleicht auch nicht so cool für alle, die da so ein bisschen nerdisch reingehen wollen.
Aber du hattest gerade, nur weil ich es nur mal damitWenn ich die eine Sache richtig verstanden habe, du meintest, dass Signals ja auch andere Signals nutzen können, aber das ist aber nur indirekt über irgendwie.
Createeffect und die anderen Primitiv.
Ja, genau über die.
Anderen Primitiv Mimo oder dann auch über CreateEffect.
Genau das wollte ich damit richtig verstanden haben. Ja, cool. Das heißt, am Ende haben wir euch noch ein bisschen gechallenged hier mit ein bisschen gedanklich koden. Wenn ich es nicht ganz verstanden habe, packen wir auf jeden Fall, obwohl die Solid. Js-seite brauchen wir nicht, die Shownotes zu packen. Guckt euch das 10 Minuten Video an, direkt auf der Solid.
Js Seite. Ja, und ich habe an der Stelle auch noch ein Video Tipp. Da suche ich mal ganz kurz raus, weil das muss ich sagen, er hat für jemand, der aus der React Welt kommt, Solid wirklich gut erklärt. Und deshalb glaube ich, ist es eine Empfehlung wert. Und zwar ist es vom Kanal Academy Mind, was auch ein deutsches, aber der auf Englisch Content macht, soweit ich weiß Deutsch. Und das Video nennt sich, das findet ihr unter Is Solid. Js The Better React ist ein 6 Minuten Video und da wird im Grunde über einen oder wird ein Großteil von dem, was wir jetzt hier auch besprochen haben, noch mal wirklich kurz und knapp erklärt und halt auch visuell, dass man es wirklich versteht. Also man muss natürlich sagen, so was wie React und View hat einfach ein größeres Ökosystem. Wenn man selbst eher auf Jobsuche ist, kann es auch Sinn machen, natürlich lieber die größeren Frameworks und Library zu lernen, weil man da einfach viel mehr im Markt findet. Auf der anderen Seite bietet natürlich jetzt SolidShare auch mit der Performance wieder Vorteile, zum Beispiel für mobile Apps, für vielleicht Mobile Games, die auf HTML aufbauen oder auch einfach Websites, die auf Geräten mit etwas weniger Performance auch einfach super laufen müssen, wo sich vielleicht React an manchen Stellen einfach schwertut.
Ja, cool.
Vielen Dank auf jeden Fall Fabian für den Einblick. Kann man schon irgendwie Werbung für deine Plattform machen oder ist sie noch in der Mache? Das heißt, da musst du noch mal kommen und Werbung machen. Aber vorwärts gleich, wir haben da gleich natürlich Pick of the Days für euch. Aber ansonsten könnt ihr auch wenn ihr Lust habt, den Fabian am wahrscheinlich 15.06. Also im Juni machen wir ein Meetup, wo du auch noch mal über SolidJS sprichst. Also wenn euch das gefallen hat und ihr vielleicht noch mal knackige Fragen stellen wollt oder einfach einen schönen Abend mit uns und lecker Getränken und Essen verbringen möchtet, dann kommt im Juni zu uns. Da ist der Fabian noch mal da und vielleicht macht er dann ein bisschen Werbung für seine Plattform. Ist bis dahin schon was zu sehen oder was ist sein Zeitplan?
Da gehe ich mal fest.
Von aus. Okay, dann macht er da Werbung. Also kommt, kommt vorbei. Ansonsten werden wir im Podcast auch noch mal drüber erzählen. Dann kommen wir jetzt zum Pick of the Days Die Pick of the Days. Ich glaube, wir haben heute alle ein, oder? Wir sind gute Gastgeber und lassen unserem Gast den Vortritt. Fabian, hast du ein.
Pick of the Day für uns? Ja, mein erster Pick, falls ich eh noch einen zweiten nennen darf, ist die Website npmstatt. Com. Die nutze ich seitdem ich jetzt ein eigenes Open Source Projekt habe, hin und wieder mal reinzuschauen, bei wie viel Downloads ich aktuell stehe. Und aktuell sind wir bei 4888 und ich kann da halt auch ganz genau sehen, wie so die Downloads pro Tag sind, pro Woche, pro Monat. Also ich kann dann halt so ein bisschen den Trend absehen und ist vermutlich für alle Leute interessant mit einem eigenen Open Source Projekt und vielleicht mal für Leute, die bei anderen Library so rein spiegeln wollen. Wobei da vielleicht dann npm Trends, wer das kennt noch mal interessanter ist.
Also kannte ich beides nicht. Ich finde es interessant. Also du hast gerade aus Spaß mal Views eingegeben. Und was ist denn, ist irgendwas im November bis Dezember passiert? Ihr hattet eine ganze Zeit täglich 725.000 Downloads und auf einmal springt es hoch auf 7 Millionen?
Ja, da war glaube ich irgendein Bug in der Codebase oder jemand hat, ich weiß nicht, ob es bewusst eine Absicht war, ich weiß nicht. Auf jeden Fall war da halt irgendwie was im Code drin, das irgendwie die Downloads getriggert hat oder so.
Also ein Bug in npm Stat oder ein Bug in View?
Ich glaube, es war ein View, weil das gleiche war oder was Ähnliches war auch bei SWELT, wenn man sich da die Statistik anschaut.
Bei React war es nicht.
Weißt du, ob.
Das.
Nur die Statistiken der NPM Registry sind?
Ich.
Denke ja. Aber da hostest du dein Open Source Projekt?
Ja, also ich meine NPM bezieht ja natürlich davon die Pakete genauso Yarn, PNPM, also die ganzen Package Manager oder sag ich mal der Kern der Package Manager holt sich ja von dort auch die Pakete.
Wobei.
Du hast recht, es gibt schon verschiedene Hosts für die NPM Packages.
Also jetzt unsere Sachen sind ja zum Beispiel bei GitHub.
In der Registry. Das ist vermutlich nicht mit drin.
Aber hat NPM automatisch Registries, die sie abgreifen? Müssen wir die, müssen wir was anderes außer die NPM Registry definieren irgendwo, aus welcher Registry sie holen soll?
Ja, wir definieren es oben.
Das heißt, standardmäßig geht es immer auf die NPM Registrier und alles andere muss definiert werden pro Paket dann?
Aber klar, wenn es NPMs heißt, wahrscheinlich geht es dann auf die NPM Registry. Aber gut zu wissen, es sind wahrscheinlich ein bisschen mehr Informationen als nur diese, ist so ein wöchentlicher Graph auf der NPM Seite?
Genau auf der NPM Seite hat man einen Graph, der letztendlich die wöchentliche Downloads Zahlen abbildet. Und hier kann man sich halt dann noch mal ein bisschen im Detail anschauen. Und wenn man NPM Pakete auch noch vergleichen will, dann gibt es da noch NPMTrends.
Com. Ist das schon dein zweiter Pick? Eigentlich nein.
Npm Trends. Com und dort kann man zum Beispiel mal solid. Js und zum Beispiel Quick eingeben.
Was vergleicht man da die Download Trends?
Genau da sieht man dann halt die Entwicklung über die Zeit.
Was okay, du hast zwar jetzt gerade schon gefühlt viele Pics genannt, aber wir lassen dich noch einen machen. Was hast du noch für uns?
Genau. Und dann noch eine weitere Sache, die interessant ist für alle, die auf Bundlesize achten. Und zwar nennt sich das bundle. Js. Com Dort kann man entweder seinen Code einfach rein pasten oder halt die Import Statement von den Funktionen, die man zum Beispiel von der Library konsumiert. Dann kann man noch über Output, über die Einstellung ein paar Sachen definieren und kann dann sich das Ganze bauen lassen und sieht dann wirklich ganz genau getreshaped und so weiter, wie viel man sich da jetzt an JavaScript ins Bündel holt. Das ist zum Beispiel deshalb interessant für mich, weil meine, also sage ich mal so eine bisschen revolutionäre Idee meiner Formularbibliothek ist, dass die modular aufgebaut ist, das hat auch Module Forms, bedeutet, wir haben nicht eine Funktion, die dir alles zurückgibt, dein Formular zu managen, sondern wir haben eine Funktion, die dir im Grunde erst mal nur den State zurückgibt bzw. Den Store, also dort wo dann der State enthalten ist. Und den wiederum kann ich dann übergeben an andere Funktionen, die ich speziell importiere, wenn ich sie brauche. Und das macht dann die Formularbibliothek komplett modular. Und wenn ich jetzt dort die Bundlesize wissen möchte, dann kann ich dort halt die Import Statements reinkopieren und mir das dann anzeigen lassen.
Zum Beispiel Modular Forms startet aktuell bei SolidGS mit ungefähr 2,5 Kilabyte, also ohne Solid. Js, das muss man rausrechnen wieder. Aber wenn man jetzt zum Beispiel auf Bundle Fobia geht, was vermutlich die meisten kennen, steht halt dann bei meiner Library 5,6 oder so aktuell. Und das wirklich nachvollziehen zu können, kann man zum Beispiel dann Bundledsche essen nutzen und halt dann die Bundle size von Solid wieder abziehen.
Okay, ja cool, vielen Dank dafür. Silbi hast du auch was für uns?
Nur eine mini kleine Kleinigkeit und ich habe es nicht ausprobiert, aber ich fand es interessant und teilenswert. Und zwar geht es da ist jetzt Solid offen. Doof. Egal, mache ich aus dem Kopf. Alsots minus Reset heißt das glaube ich, ist von einem Dude, dem ich auf Twitter folge und das ist ein TypeScript Helferchen, was ein paar Bildin Sachen von TypeScript in Anführungszeichen reparieren soll, ein bisschen niceer macht. Und zwar große Sache zum Beispiel, wenn ich filter auf Boolien, dann habe ich ja später keine undefined und keine Nulls mehr irgendwie da drin. Und bisher muss ich das irgendwie ein bisschen umständlich typisieren, damit TypeScript das auch mitbekommt. Und solche Sachen hat er da drin gefixt. Ich habe es selber noch nicht ausprobiert, aber klingt alles ganz sinnvoll und er testet das wirklich auch auf Herz und Nieren und ist da sehr überlegt, welche Funktionen er rein nimmt oder nicht. Zum Beispiel dieses mit „Möchte ich meinen Object Keys oder so wirklich wie Unions typisieren oder nicht? So, wo man sich mal fragt, so ja, warum ist das eigentlich nicht so und so? Und er hat es jetzt halt nicht reingenommen aus Gründen und so. Und er schreibt das auch alles nieder, jedes Häfchen, was er rein nimmt und warum?
Das ist wirklich cool, weil ich bin in letzter Zeit häufiger auf das Problem gestoßen, dass wenn ich zum Beispiel ob Objects dort Entries nutze, dann halt über ein Objekt drüber zu gehen, dass dann halt die Typisierung einfach nicht stimmt. Und selbst wenn ich die irgendwie teilweise dann manuell im Sack nutzt, bitte als Typ, also über die Generics, diesen Datentyp oder selbst dann irgendwie hat es immer Probleme gemacht und da wäre das vermutlich dann die Lösung.
Genau. Wobei ich bin mir nicht ganz sicher, aber ich glaube eben gerade diese Object Entries, Object Keys, Object Value Sachen hat er extra rausgelassen.
A common tasks is to probe beter typing to object Keys and... Ah ja, ich sehe es.
Zumindest eine Erklärung warum. Also muss ich mir das mal durchlesen.
Bei uns haben wir es trotzdem in die Globus reingepackt. Ich muss ja vielleicht auch mal durchlesen, warum nicht? Warum es eine schlechte Idee ist. Aber wie gesagt, wie gesagt, er denkt viel drüber nach. Er begründet das auch anders.
Ja, cool. Dann schließe ich mal ab mit den Pick of the Days. Und zwar haben Sebi und ich uns gekloppt den Pick of the Days und zwar unserem neuesten Lieblingsschatzie, dem ARK Browser von der Browser Company, wo zu der Sebi, mich und den Sven, unser anderes Teammitglied eingeladen hat und es wirklich ein Browser, der bei uns im gesamten Team den Chrome ersetzt hat und wir nicht gedacht haben, dass das ein Browser noch mal schafft. Letztens hat es ja auch Microsoft mit Edge probiert, weil sie mich bisschen rein getrackt haben in ihre Chat-GPT-Bing-Implementierung, die ich aber natürlich dann nicht weiter benutzt habe. Aber ARK ist echt eine coole Empfehlung. Also grundsätzlich ein paar coole Features. Das, was mich auf jeden Fall überzeugt hat, irgendwie sind, sie haben ein ganz cooles Prinzip von, sie nennen es jetzt, sagen wir mal, Profile. Also man kennt das, wenn ich in Chrome irgendwie, dann kann ich mir ein Profil anlegen und sagen, okay, ich habe mein privates Profil, mein Home-Profil und so, und ich will gar nicht so ganz ins Detail gehen, aber zumindest Ihre Implementierung davon. Ich habe mehrere Profile, Workprofile, das private Profil ist super cool umgesetzt. Generell auch, wie Sie irgendwie Favoriten sortieren und ihre Tabs.
Ich glaube, Sie gehen sehr stark über den Punkt, wie man Tabs organisiert, so dass du auch jeden Tag, wenn dann … Also gerade für Tabs Messies ist es einfach sagen wir einfach mal, es hat coole Konzepte. Ich glaube im Detail zu erklären, macht gar nicht so viel Sinn, es einfach mal auszuprobieren. Der überzeugt einfachDas sind so ein paar Dinge, von denen man vorher gar nicht wusste, dass man es ungefähr unbedingt braucht. Mal so ein paar Favoriten Links, wie zum Beispiel, wenn man sich seinen Kalender in die Favoriten packt und dann nur über den Link drüber hovert, kriegt man so eine kleine Preview von seinen nächsten Kalender Terminen und so und es sind irgendwie viele kleine Dinge, die super cool durchdacht sind. Vielleicht auch einfach so was wie du hast einen Screenshot Feature, der automatisch dir zum Beispiel nach dem du HTML Elemente oder bestimmte Elemente auf der Seite erkennt und du nur von bestimmten Elementen einen Screenshot machen kannst, ohne dass du sie irgendwie genau aufziehen musst und irgendwie dir hier dieses Formular, wenn du das noch screenen willst, irgendwie deinen Frame genau setzen musst. Er kennt da war es ein Formular. Ich probiere mal davon einen Screenshot anzubieten oder von der gesamten Seite und echt viele kleine coole Dinge.
Ist glaube ich aktuell gerade noch zumindest in einer closed, aber zumindest closed, ob man es beter sagen kann, weiß ich nicht. Aber ich glaube, wir haben noch ein paar zu verschenken. Also wenn jemand interessiert ist, wir schicken euch ein paar Links raus. Schickt uns eine E-Mail an podcast@programmier.
Bar. Das heißt, ich kann es nicht einfach so aktuell runterladen?
Nee, über uns könnt ihr eine einladungschicken, die wir noch bekommen. Unsere paar, die wir noch haben, verschenken wir an euch. Also schreibt uns eine E-Mail, die first com.
Aber ich glaube, man kann sich auch auf die Warteliste setzen. Ich frage nur, wann das.
Dann … Genau. Ich war auf der Warteliste jetzt seit anderthalb Wochen und habe es noch nicht bekommen und habe dann über Sebi die Schulter geguckt und gesehen, er hat ihn schon und hat mir eine Einladung geschickt.
Ich weiß auch nicht, warum ich da reingerutscht bin.
Also schreibt uns. Wir verschenken unsere paar Einladungen, die wir noch haben. Dann vielen Dank Fabian, vielen Dank für deine Zeit. Wir sehen uns dann spätestens im Juni wieder und wir wünschen dir viel Erfolg mit deiner eLearning Plattform und machen dann natürlich gerne Werbung, wenn da was am Start ist. Ansonsten vielen Dank fürs Zuhören. Gibt uns wie immer Feedback, Podcasts sind programmierbar über unsere Website und bis zum nächsten Mal. Bis zum nächsten Mal.