Dioxus 0.5: Web-, Desktop- und Mobile-Apps mit Rust entwickeln
(dioxuslabs.com)- Das Rust-GUI-Framework Dioxus 0.5 vereinfacht den Entwicklungsablauf für Web, Desktop, Mobile und Fullstack deutlich, vor allem durch die Neuschreibung von
dioxus-coreund die Entfernung von unsafe Code - Zwischen 0.4.3 und 0.5.0 kamen mehr als 100.000 Zeilen Code und über 1.400 Commits hinzu; der neue Core wurde so umgebaut, dass Lifetimes und die Abhängigkeit von
Scopeentfallen - Die bisherige, auf
use_stateunduse_refzentrierte Zustandsverwaltung wird durch eine kopierbareSignal-API ersetzt, wodurch in Event-Handlern und Futures weniger wiederholtesClonenötig ist - Mit einem einzigen
dioxus::launchund dem Ablaufdx serve --platformlassen sich Web-, Desktop- und Fullstack-Apps starten; die CLI übergibt automatisch die zur Zielplattform passenden Build-Features - Asset-Hot-Reload, eine Überarbeitung der Events, Verbesserungen beim Desktop-Rendering und Streaming für Server Functions erweitern zusammen den Einsatzbereich einer einheitlichen Rust-Codebasis
Release-Ausrichtung von Dioxus 0.5
- Dioxus ist eine Bibliothek zum Erstellen von GUIs mit Rust und wird für die Bereitstellung von Web-, Desktop- und Mobile-Apps eingesetzt
- Das Release 0.5 wurde mit dem Ziel entworfen, die von der Community gewünschte Vereinfachung, Robustheit und höhere Ausgereiftheit zu erreichen
- Die wichtigsten Änderungen sind:
- vollständige Neuschreibung von
dioxus-coreund Entfernung von unsafe Code - Einführung einer auf
Signalbasierenden API anstelle vonuse_stateunduse_ref - Entfernung aller Lifetimes und des Zustands
cx: Scope - eine einzige
launch-Funktion zum Starten von Apps auf allen Plattformen - Asset-Hot-Reload mit Unterstützung für Tailwind und Vanilla CSS
- Überarbeitung des Event-Systems mit Zugriff auf native
WebSys-Event-Typen - Integration von Error Boundary, Server Future und Suspense
- 5-fache Verbesserung der Desktop-Reconciliation
- Streaming für Server Functions und Fullstack-Hot-Reload
- vollständige Neuschreibung von
- Für Nutzer, die von Dioxus 0.4 aktualisieren, steht ein migration guide bereit
Entfernung von Lifetimes und Scope
- Von Dioxus 0.1 bis 0.4 hatten Werte innerhalb von Komponenten die Lifetime
'bump; dadurch konnten Hooks, Props und Scope in Event-Listenern ohne Klonen verwendet werden - In Event-Handlern funktionierte das meist gut, aber Futures in Dioxus mussten
'staticsein, sodass Werte vor dem Verschieben in eine Future geklont werden mussten - Bei Lifetime-Fehlern konnten verwirrende Meldungen entstehen, etwa dass
cxlänger als'staticleben müsse, statt den eigentlichen Hook zu benennen - Dioxus 0.5 entfernt
Scopeund die'bump-Lifetime und machtElementlifetime-frei - Komponenten können Props nun direkt ohne Scope-Parameter entgegennehmen
- Beispiel:
fn MyComponent(name: String) -> Element
- Beispiel:
- Runtime-Funktionen lassen sich nicht nur innerhalb von Komponenten, sondern auch direkt in Futures und Event-Handlern verwenden
- Da
Elementnun'staticist, kann es auch innerhalb von Hooks genutzt oder über die Context-API bereitgestellt werden - Diese Änderung schafft eine Grundlage, mit der sich APIs wie virtuelle Listen oder Offscreen-Rendering leichter implementieren lassen
Entfernung von unsafe aus dioxus-core
- Die Entfernung der
'bump-Lifetime und von Scope eröffnete die Möglichkeit, unsafe Code innerhalb von Dioxus zu reduzieren dioxus-core 0.5enthält keinen unsafe Code- In einigen Abhängigkeiten verbleibt eine kleine Menge unsafe Code; das Dioxus-Team plant, diese im Verlauf des 0.5-Release-Zyklus zu entfernen
- Der verbleibende unsafe Code wird entweder als schlicht entfernbar oder als wegen FFI notwendig eingestuft
Signal-basierte Zustandsverwaltung
- Dioxus 0.5 führt Signal als zentrale Zustands-Primitive für Komponenten ein
- Signal hat gegenüber dem bisherigen
use_stateunduse_refzwei Vorteile- Es ist immer
Copy - Es erfordert keine manuelle Subscription
- Es ist immer
-
Copy-Zustand
Signal<T>istCopy, auch wenn der enthaltene WertTnichtCopyist- Dieses Verhalten wird durch die ohne unsafe implementierte Crate generational-box ermöglicht
- Bei Bedarf kann ein Signal
Send+Syncgemacht werden, sodass es zwischen Threads verschoben werden kann - Durch die Kombination aus Copy-Zustand,
Send+Sync-Signal und statischen Komponenten lässt sich Zustand leicht an die benötigten Stellen verschieben, etwa in Futures, Event-Handler oder Threads - Die Speicherverwendung ist fast identisch mit 0.4, aber explizites
Cloneist nicht mehr nötig
-
Intelligente Subscriptions
- Signal entscheidet feiner abgestimmt, welche Komponente neu ausgeführt werden soll, wenn sich ein Wert ändert
- Eine Komponente wird nur dann erneut ausgeführt, wenn sie den Signal-Wert gelesen hat
- Lesezugriffe in async Tasks oder Event-Handlern werden nicht als Subscription für eine erneute Komponentenausführung behandelt
- Wenn ein Parent per Button-Klick ein Signal ändert, den Wert aber nicht direkt liest, und nur das Child den Wert liest, wird nur das Child neu gerendert
- Durch diese Struktur wird Fermi, eine separate Crate für Zustandsverwaltung, nicht mehr benötigt
- Fermi stellte eine
use_state-ähnliche API bereit, diestaticals Schlüssel verwendete - In Dioxus 0.5 kann
GlobalSignalin einemstaticabgelegt und wie ein normales Signal genutzt werden - Signal funktioniert auch mit der Context-API, sodass Zustand ohne separaten
use_shared_state-Hook zwischen Komponenten geteilt werden kann - Wenn ein Signal in Hooks wie
use_futureoderuse_memogelesen wird, wird dieses Signal automatisch zu den Hook-Abhängigkeiten hinzugefügt
CSS- und Asset-Hot-Reload
- Dioxus 0.5 implementiert im Rahmen der Überarbeitung des Asset-Systems Hot-Reload für CSS-Dateien im Asset-Verzeichnis
- Wenn eine CSS-Datei in RSX vorkommt, überwacht die
dx-CLI diese Datei und streamt Updates sofort in die laufende App - Unterstützt werden Web, Desktop und Fullstack; Mobile-Unterstützung soll in einem künftigen Mobile-fokussierten Update folgen
- In Kombination mit dem Tailwind-Watcher wird auch Tailwind-CSS-Hot-Reload unterstützt
- In VSCode lassen sich über die custom regex extension auch Hinweise für Tailwind-Klassen erhalten
- Änderungen können gleichzeitig an mehrere Geräte gestreamt werden, sodass Hot-Reload auf allen Zielgeräten erfolgt
Überarbeitung des Event-Systems
- Seit dem ersten Release nutzt Dioxus ein Synthetic-Event-System, um eine Cross-Platform-Event-API bereitzustellen
- Synthetic Events sind hilfreich für plattformübergreifendes Event-Verhalten und Netzwerkserialisierung, haben aber auch Grenzen
- Dioxus 0.5 legt die zugrunde liegenden Event-Typen der jeweiligen Plattform offen und stellt zusätzlich Traits für die Cross-Platform-API bereit
- Diese Änderung hat zwei Vorteile
- Benötigte Informationen können direkt aus dem Plattform-Event-Typ gewonnen oder an andere Bibliotheken weitergegeben werden
- Event-Code, den eine App nicht nutzt, kann per Bundle Splitting ausgelagert werden
- Im Hello-World-Beispiel sinkt die gzipped Größe um etwa 25 %
- Tipps für kleine Bundles finden sich im Dioxus optimization guide
Cross-Platform-API zum Starten
- Dioxus 0.5 führt eine neue Cross-Platform-API zum Starten von Apps ein
- Statt separate Renderer-Pakete zu importieren, genügt es, in der Crate
dioxusein Feature zu aktivieren und die Funktionlaunchaus dem Prelude aufzurufen - Eine einzelne App kann für folgende Plattformen ausgeführt werden
- Desktop:
dx serve --platform desktop - SPA Web:
dx serve --platform web - Fullstack:
dx serve --platform fullstack
- Desktop:
- Die CLI übergibt je nach Zielplattform automatisch die passenden Build-Features
Asset-System-Beta und Manganis
- In Dioxus und Web-Apps können Asset-Pfade leicht veralten, Links können sich zwischen Desktop und Web unterscheiden, und Assets, die in das Bundle aufgenommen werden sollen, müssen manuell hinzugefügt werden
- Assets können außerdem zu Performance-Engpässen werden
- Im Beispiel des Dioxus-Mobile-Guides brauchte Version 0.4 sieben Sekunden zum Laden und übertrug 9 MB an Ressourcen
- Der Mobile-Guide für 0.5 lädt mit denselben Bildern in unter einer Sekunde und benötigt nur ein Drittel der Ressourcen
- Dioxus 0.5 führt das neue Asset-System manganis ein
- Es ist in die CLI integriert und prüft, bündelt und optimiert App-Assets
- Da die API noch instabil ist, wird es als separate Crate veröffentlicht
- Wenn Assets mit dem Makro
mg!umschlossen werden, erkennt die CLI sie automatisch - Weitere Details stehen in den manganis docs
- Während des 0.5-Release-Zyklus ist geplant, auch für Manganis-Assets Hot-Reload hinzuzufügen
5-fache Verbesserung des Desktop-Renderings
- Dioxus nutzt mehrere Optimierungen, um Rendering-Diffs schnell zu machen
- Templates sorgen dafür, dass der Diff für statische Teile des
rsx!-Makros übersprungen wird - In Dioxus Web werden DOM-Änderungen aus Rust heraus über sledgehammer schnell angewendet
- Dioxus 0.5 nutzt denselben Ansatz auch für das Anwenden von Änderungen über das Netzwerk
- Desktop- und LiveView-Renderer kommunizieren Änderungen nicht mehr per JSON, sondern über ein binäres Protokoll
- Bei renderlastigen Aufgaben reduziert der neue Renderer die Zeit zum Anwenden von Änderungen im Browser auf ein Fünftel und die Latenz auf die Hälfte
- Ein Benchmark, bei dem der Renderer in Dioxus 0.4 ständig hängen blieb, läuft in Dioxus 0.5 flüssig
Komfortfunktionen beim Schreiben von Komponenten
- Dioxus 0.5 unterstützt das Erweitern bestimmter Elemente und das Ausbreiten von Attributen auf ein Element
- Beispiel: Eine
ImgPlus-Komponente, die Attribute desimg-Elements erweitert, kann normaleimg-Attribute wiewidth,heightundsrcunverändert entgegennehmen
- Beispiel: Eine
- Beim Übergeben von Werten an Attribute und Komponenten kann die Kurzschreibweise für Struct-Initialisierung verwendet werden
- Statt
class: classkann manclassschreiben
- Statt
- Kurzattribute funktionieren für alles, was
IntoAttributeimplementiert; auch Signal profitiert davon - Signal-Attribute überspringen das Diffing noch nicht, sollen aber im Verlauf des 0.5-Release-Zyklus als Performance-Optimierung ergänzt werden
- Über mehrere Zeilen verteilte Attribute können zusammengeführt werden
- Wenn demselben
class-Attribut bedingte Werte hinzugefügt werden, werden sie mit Leerzeichen als Trenner zusammengeführt - Das ist wichtig für Bibliotheken wie Tailwind, die Compile-Time-Parsing benötigen und gleichzeitig dynamische Verarbeitung zur Laufzeit brauchen
- Diese Syntax ist in den Tailwind-Compiler integriert und entfernt den Runtime-Overhead von Bibliotheken wie
tailwind-merge
- Wenn demselben
Streaming für Server Functions und Fullstack
- Dioxus 0.5 unterstützt die aktuelle server functions crate, die Streaming-Daten unterstützt
- Server Functions können Daten zum Client streamen oder Daten vom Client zum Server streamen
- Eine Streaming-Server-Function lässt sich erstellen, indem man einen Ausgabetyp definiert und aus der Server Function
TextStreamzurückgibt - Das eignet sich, um Clients während lang laufender Aufgaben zu aktualisieren
- Es gibt ein Beispiel, das mit Kalosm und einem lokalen LLM auf gewöhnlicher Hardware eine ähnliche Funktionalität wie ein OpenAI-ChatGPT-Endpoint bereitstellt
- Beispiel-Repository: https://github.com/ealmloff/dioxus-streaming-llm
- Die CLI unterstützt nun die Plattform
fullstackund bietet Hot-Reload sowie parallele Builds für Client und Serverdx servedx serve --platform fullstack
LiveView, Asset-Handler und Dateiverarbeitung
- In Dioxus 0.5 funktioniert der Router standardmäßig in LiveView-Apps
- Zugehöriger PR: https://github.com/DioxusLabs/dioxus/pull/1505
- Dioxus Desktop unterstützt Custom Asset Handler
- Zugehöriger PR: https://github.com/DioxusLabs/dioxus/pull/1719
- Custom Asset Handler ermöglichen es, Daten aus Rust-Code ohne Umweg über JavaScript effizient an den Browser zu streamen
- Sie eignen sich für bandbreitenintensive Kommunikation wie Video-Streaming
- Zugehöriger PR: https://github.com/DioxusLabs/dioxus/pull/1727
- gstreamer- oder webrtc-Daten können direkt an die WebView übergeben werden, wodurch die Notwendigkeit sinkt, Frames selbst zu kodieren und zu dekodieren
- Auch Datei-Drops auf dem Desktop sind nativ in das Event-System integriert
Fehlerbehandlung
- Dioxus erleichtert über Error Boundary und das
throw-Trait die Fehlerbehandlung in übergeordneten Komponenten - Der
throw-Ansatz kombiniert die Vorteile von Fehlerzustand und frühem Return - Bei einem
Result-Typ, derDebugimplementiert, kannthrowaufgerufen werden, um ihn in einen Fehlerzustand umzuwandeln, und mit?früh zurückgegeben werden - Die Komponente
ErrorBoundaryrendert eine andere Komponente, wenn in ihren Children ein Fehler geworfen wurde ErrorBoundarykann verschachtelt werden, sodass Fehler auf mehreren Ebenen einer App abgefangen werden können- Dieses Muster ist nützlich, um bei nicht behebbaren Fehlern einen globalen Fehlerzustand zu behandeln, statt zu panicken oder für jeden Fehler den Zustand manuell zu verwalten
Developer Experience und Templates
- Dioxus führte Hot-Reload in 0.3 ein, ergänzte es in 0.4 für Desktop und aktiviert es in 0.5 standardmäßig
- Wenn eine App mit
dx servegestartet wird, ist Hot-Reload im Entwicklungsmodus standardmäßig eingeschaltet - Auch wenn Hot-Reload in Desktop-Apps nicht möglich ist und eine vollständige Neukompilierung nötig wird, bleibt der Zustand geöffneter Fenster erhalten und wird wiederhergestellt
- Größe und Position des App-Fensters bleiben erhalten
- Das reduziert Situationen, in denen die App bei jeder Bearbeitung den gesamten Bildschirm blockiert
- Die neuen Templates sind so organisiert, dass Web-, Desktop-, Mobile-, TUI- und Fullstack-Apps mit einem einzigen Befehl erstellt werden können
- Die Standard-App von
dx newwurde stärker an create-react-app angelehnt- Sie enthält Assets, CSS und grundlegende Deployment-Einstellungen
- Sie enthält Links zu nützlichen Ressourcen wie dioxus-std, VSCode Extension, Dokumentation und Tutorials
Dioxus Community und Ökosystem
- Die Dioxus Community hat wichtige Ökosystem-Crates für das 0.5-Release aktualisiert
- Crates wie icons, charts und eine Dioxus-spezifische Standardbibliothek wurden so vorbereitet, dass sie zum Start von 0.5 sofort nutzbar sind
- Das Projekt
Dioxus Communityist eine neue GitHub-Organisation, die wichtige Crates aktuell halten soll, auch wenn ursprüngliche Maintainer aussteigen - Wer Bibliotheken für Dioxus entwickelt, kann von Dioxus-Seite Unterstützung bei der Wartung erhalten; Ziel ist, sie faktisch mit „Tier 2“-Support zu betreuen
Geplante Funktionen
- Zu den Plänen nach 0.5 gehören:
- Stabilisierung und tiefere Integration des Asset-Systems
- direktes Bundle Splitting der ausgegebenen
.wasmzusammen mit Lazy Components - Islands und resumable Interactivity, Signal-Serialisierung
- Zusammenführung von Server Components und LiveView in Fullstack
- verbesserte Devtools und ein Test-Framework
- umfassende Überarbeitung von Mobile
- Fullstack-Überarbeitung mit WebSocket, SSE, Progressive Forms und mehr
Vorschau auf Servo-basiertes Dioxus-Blitz
- „Blitz 2.0“ von Dioxus-Blitz zielt darauf ab, Servo zu integrieren und mit derselben CSS-Engine wie Firefox natives Rendering über WGPU zu ermöglichen
- Nico Burns, der die Layout-Bibliothek Taffy entwickelt hat, ist in Vollzeit dazugestoßen, um diese Arbeit voranzutreiben
- In der Demo wird
google.commit 900 FPS auf der GPU gerendert - Die aktuelle Implementierung ist noch nicht vollständig, und auch das Rendering von
google.comwirkt noch etwas unbeholfen, nähert sich aber schnell einem nutzbaren Niveau - Das Repository ist unter https://github.com/jkelleyrtp/stylo-dioxus zu finden
Mitwirken
- Das Dioxus-Projekt wünscht sich Beiträge in folgenden Bereichen
- Übersetzung der Dokumentation
- Bearbeitung von „Good First Issues“
- Verbesserung der Dokumentation
- Beiträge zur CLI
- Beantwortung von Fragen in der Discord-Community
- Das Dioxus-Team bedankt sich für die Unterstützung der Community im restlichen Jahr 2024 und bittet um Hilfe dabei, die App-Entwicklung zu verändern
1 Kommentare
Meinungen auf Hacker News
Als ich mit der Arbeit begann, war es Version 0.2, und mit den Änderungen in 0.5 scheint fast die gesamte Komplexität, mit der ich damals zu kämpfen hatte, verschwunden zu sein. Ich habe es noch nicht selbst ausprobiert, aber durch den Wegfall der Lifetimes und die geringere Notwendigkeit, ständig zu klonen, dürfte es deutlich angenehmer werden.
Es gibt ziemlich viele Rust-Frameworks, die native reaktive UIs für Deployment auf Desktop, Web/Wasm, Mobile usw. ermöglichen wollen (https://github.com/flosse/rust-web-framework-comparison), und ich mache mir Sorgen, dass man bei einer falschen Wahl am Ende ein aufgegebenes Framework pflegen oder eine schmerzhafte Migration durchführen muss.
Bei Rust-HTTP-Server-Frameworks gab es ähnlich viele, und inzwischen scheinen Axum, Actix und Rocket vorn zu liegen; zugleich wirkt es so, als bewege sich die Community in Richtung Axum, sodass ich mich frage, ob die Wahl von Actix ein Fehler war. Ich wüsste gern, ob es Anzeichen dafür gibt, dass Dioxus sich durchsetzen wird, und ob es neben großer Community, YC-Unterstützung und Momentum weitere Kennzahlen gibt, die dafür sprechen, es jetzt zu wählen.
Außerdem würde ich gern wissen, ob Leptos und Yew ebenfalls wichtige Konkurrenten sind und aus welchen Gründen sie besser oder schlechter als Dioxus sind. Unser Unternehmen hat stark in Rust, Actix und Bevy investiert, und künftig wollen wir Frameworks wie Bevy und Dioxus kombinieren, um native Desktop- und Mobile-Clients zu bauen.
Und ich frage mich auch, ob der Name Dioxus von Deoxys aus Pokémon stammt. Das Logo fühlt sich so an, aber in der Codebasis gibt es keine Pokémon-Referenzen.
Vor etwa neun Monaten habe ich mit Dioxus ein GUI-Frontend für sshfs gebaut, und bis zu dem Punkt, an dem ich gegen eine Wand lief, weil die Entwickler irgendeine Funktion noch nicht fertiggestellt hatten, wirkte es wie ein wirklich hervorragendes GUI-Framework.
State zwischen verschiedenen Kontexten zu teilen, ist gelegentlich ebenfalls schmerzhaft, aber das war bei jedem GUI-Framework so, das ich je benutzt habe, unabhängig von Sprache oder zugrunde liegender Technik. Dioxus 0.5 sieht hier nach einem großen Fortschritt aus. Mein Blog rendert einen beträchtlichen Teil des HTML mit Dioxus, und da ich es nicht bis an seine Grenzen ausreize, funktioniert es sehr gut.
Allerdings finde ich die Lösung zur Entfernung der Lifetimes etwas merkwürdig. generational-box wirkt auf mich wie eine Art Garbage Collector für Arme, und ich frage mich, wie stark die Performance-Auswirkungen waren.
Außerdem ist der Link
[generational-box]([https://crates.io/crates/generational-box](<https://crates.io/crates/generational-box>))kaputt.use_hookbesitzt einen Wert für die Lebensdauer der Komponente, daher wird dieser Wert gedroppt, wenn die Komponente verschwindet. Alle Signals verwenden weiterhinuse_hook, daher ist auch ihre Lebensdauer identisch.GenerationalBox::new()außerhalb vonuse_hookaufzurufen, wird normalerweise nicht empfohlen, deshalb gibt es keine Performance-Auswirkungen.Wenn man in einer Schleife massenhaft
GenerationalBox::new()aufruft, bleibt dieser Müll zwar bis zum Drop der Komponente erhalten, aber meistens wird man in eine Map oder einen Vec pushen bzw. daraus poppen, und dann gilt die normale Speichersemantik.Ich verstehe, dass es eine Art Arena-Allokation ist, aber ich verstehe nicht, wie sie „Kopieren ohne Kopieren“ unterstützt und warum die Erklärung sicher ist, dass intern eine
RefCell-Arena mit Generationen angelegt wird undGenerationalBoxCopyist.Ich verstehe, dass man Pointer auf statische Daten erzeugen kann, aber was passiert bei Werten ohne statische Lebensdauer?
Die Datenreferenz bleibt über die Lebensdauer des Programms hinweg bestehen. Eine generational box ermöglicht es, Daten aufzunehmen, die kürzer leben als das Programm, aber diese Daten dürfen keine Referenzen enthalten. Wenn die enthaltenen Daten gedroppt werden, wird diese Box für eine andere Allokation wiederverwendet.
Abgesehen davon, dass Boxen statt einer zentralisierten Arena verwendet werden, ist der Ansatz einer generational Arena sehr ähnlich; das ist eine Entscheidung, um Locking-Probleme zu vermeiden. Wenn man nach dem Drop versucht, über eine
Copy-Referenz auf die Daten zuzugreifen, schlägt das mit einer guten Fehlermeldung fehl.Copyeine bestimmte Bedeutung.Wenn ein Typ das
Copy-Trait implementiert, heißt das, dass er permemcpykopiert werden kann; das ist eher eine flache Kopie als eine tiefe Kopie.Deshalb verstehe ich es nicht als „Kopieren ohne Kopieren“, sondern so, dass man einen nicht-
Copy-Typ wie einenCopy-Typ behandeln kann. In der README steht, dass statische Inhalte erforderlich sind; bei Werten ohne statische Lebensdauer lautet die Antwort also: „Das geht nicht.“Mir gefällt, dass Dioxus vieles von dem übernimmt, was React erfolgreich gemacht hat, und darauf aufbauend schnell innoviert und ausliefert. Ich freue mich darauf, die Signals dieser Version auszuprobieren.
Ich erkenne an, was React für JS und das Web Gutes getan hat, und auch seinen Namen, aber wenn man 2024 eine Sprache oder DSL von Grund auf entwerfen kann, glaube ich nicht, dass Code für „reaktive UI“ unbedingt wie React aussehen muss.
Damit will ich nicht sagen, dass SwiftUI perfekt ist, aber Code in SwiftUI wirkt auf mich viel sauberer organisiert und gekapselt als vergleichbarer Code in React.
Der eigentliche Vorteil von JSX für plattformübergreifende GUIs ist höchstens, dass man bestehende Libraries aus dem Web wiederverwenden kann. Bei RSX scheint der „portierbare Wert“ eher gering zu sein, abgesehen davon, dass Entwickler ihr Konzeptwissen zu JSX auf RSX übertragen können. Da ist es ein besserer Kompromiss, gleich ein neues Paradigma zu lernen, das man objektiv für besser hält als das React/JSX-Paradigma.
Kurz gesagt: Es wäre schön, ein Projekt zu haben, das „SwiftUI, aber plattformübergreifend“ ist, doch das gibt es noch nicht. @Tokamak/TokamakUI kenne ich, aber es wirkt noch sehr unfertig und die Aktivität scheint nachgelassen zu haben.
Derzeit werden nur native Desktop-Apps für Linux/mac/windows unterstützt, aber WASM-, Web- und Mobile-Support ist geplant.
Sie soll die erste dezentrale Website werden, die Leute sehen, die Freenet eingerichtet haben. Sie ist auch ein wenig ähnlich zu Kweb, einem Kotlin-Web-Framework, an dem ich über die Jahre sporadisch gearbeitet habe – besonders bei der Zustandsverwaltung und der DSL-Art, wie Code auf HTML abgebildet wird. Bisher gefällt es mir.
https://freenet.org/
https://kweb.io/
Tatsächlich bin ich Kotlin-Fan und mag Kotlin-DSLs sowie das Concurrency-Modell.
Tauri steckt das Frontend in eine Webview, und mit nativen Rust-Funktionen muss man wie bei Electron über eine IPC-Grenze kommunizieren.
Bei Dioxus liegt der Rust-Code auf der nativen Seite, daher braucht man für Dinge wie Dateisystemzugriff oder WebSockets kein IPC. Tauri zwingt einen dazu, das Frontend zu WASM zu kompilieren, und viele interessante Rust-Crates lassen sich nicht nach wasm kompilieren.
Es ist schwer in Worte zu fassen, wie sehr eine fehlende IPC-Grenze die Entwicklung vereinfacht. Da die Dioxus-Tools nur auf Rust abzielen, kommt man in unter einer Minute von null zu einer gebündelten
.app. Ein neuer Build dauert etwa 12 Sekunden, ein neues Bundle etwa 20 Sekunden.Trotzdem mag ich die Flexibilität von Tauri sehr, nämlich dass man im Frontend alles verwenden kann, was als webkompatible UI funktioniert, und man kann Dioxus auch innerhalb einer Tauri-App nutzen.
Es ist gut, dass Dioxus das im README direkt behandelt, aber mich interessieren auch praktische Erfahrungen von Leuten, die beides verwendet haben.
Ich habe mit Tauri eine Desktop-Spielzeug-App gebaut und geprüft, ob IPC schnell genug ist, dass ein Web-Frontend bei jedem Tastendruck aktualisiert und arbeitet, ohne Verzögerung – die Antwort war „ja“. Ob man bei jedem Tastendruck große Dateien vom Frontend in die Rust-Schicht schicken und wieder zurück ins Frontend bekommen kann, war zumindest bei meiner naiven Implementierung „nein“.
Sowohl Tauri als auch Dioxus haben viele gute Einsatzfälle, und in manchen davon dürfte Dioxus besser passen. Ich würde gern Vergleichsberichte hören wie „Wir haben uns in unserem Projekt wegen X und Y für Dioxus oder Tauri entschieden“. Dioxus sieht wirklich cool aus, ich freue mich darauf, es auszuprobieren.
stylo ist der Teil von Servo, der mit Firefox geteilt wird. Langfristig wollen wir die Leute auf den WGPU-Renderer bringen, aber der ist noch ziemlich früh, und viele Firmen, die Dioxus einsetzen, wissen pragmatisch, dass Webviews für etwa 90 % einer App eine ausreichend gute Lösung sind.
Ich verstehe, dass Leute manchmal zu leichtfertig
unsafeverwenden, aber auch die Standardbibliothek ist voll vonunsafe, und die Grenze dort zu ziehen wirkt manchmal wie eine Linie im Sand.Es gibt drei Stellen: ein paar FFI-Korrekturen für iOS, die Implementierung, die Funktionsaufruf-Syntax für signal ermöglicht, und die Implementierung von Send/Sync für eine ID, die einen Pointer als Hash verwendet.
Letzteres könnte man, wenn ich jetzt darüber nachdenke, vielleicht entfernen, indem man es durch
usizeersetzt.unsafeetwas übermäßig Angst haben können.Trotzdem ist es nicht unbedingt eine schlechte Entscheidung, wenn ein Crate-Autor sich zum Ziel setzt,
unsafeaus seinem Crate zu entfernen.Crate-Autoren, die alles
unsafeentfernen wollen, versuchen oft, die Vertrauenslast für Nutzer zu verringern. Das sehe ich als die Stärke des Schlüsselwortsunsafe. Eigentlich hätte es vielleicht intrust_me-Blöcke undcheck_yourself-Funktionen aufgeteilt werden sollen.unsafebeschränkt die Diskussion über Speichersicherheit auf sehr enge und auditierbare Stellen im Code und schafft zugleich eine neue, handhabbare Diskussion über Vertrauen.use*-Namenskonvention eingeführt hat, aber ich frage mich, warum die Funktion zum Erzeugen eines neuen Signals in Dioxususe_signalheißt.Ist
let mut count = use_signal(|| 0);nicht ein Aufruf, der ein neues Signal erzeugt? Das Signal wird nicht bei jedem Rendern neu erstellt, und genau das ist doch der Kern von Signals.In SolidJS erstellt man ein Signal mit createSignal, etwa
const [count, setCount] = createSignal(0), und das ist deutlich verständlicher.API-Namen sind wichtig, weil State-Hooks anders funktionieren und zusätzliche Anforderungen wie
useMemoentstehen können. Ich frage mich, ob es außer dem Wunsch, näher an React zu wirken, einen Grund gab, den Namenuse_signalzu wählen.Es ist eher näher an Preact als an Solid.
Zu den Optimierungen gehören das Abtrennen dynamischer UI-Teile in separate „Diff Bins“, standardmäßige Memoization und dass Signals Eigenschaften implizit als dirty/managed markieren.