features · Sep 3, 2014

Quire: Eine große Anwendung mit Dart entwickeln

✦
KI-übersetzt
· Auf Englisch ansehen

Quire-Anwendung, entwickelt mit der Programmiersprache Dart

Zuletzt aktualisiert: 28. Mai 2026

TL;DR

Quire (53.992 Zeilen, 1.620 KB Dart-Code) wurde 2014 mit Dart auf Client und Server entwickelt. Für eine feinere DOM-Kontrolle setzte das Team auf DQuery und Bootjack statt auf AngularDART oder Polymer.dart. Die zentralen Entscheidungen haben auch 2026 noch Bestand: starke Typisierung im gesamten Stack, gemeinsame Datenmodelle für Client und Server, Event Loop auf dem Server und Tree Shaking für die JS-Ausgabe.

Quire ist nicht die erste Webanwendung, die in Dart geschrieben wurde, und wird auch nicht die letzte sein. Aber sie könnte die erste App sein, die sich so stark auf Dart stützt, sowohl auf dem Client als auch auf dem Server.

Logo und Framework der Programmiersprache Dart für die Webanwendung Quire

Quire ist ein Aufgabenmanager, der Spaß macht und durch und durch auf einer Baumstruktur aufbaut. Das Projekt selbst umfasst 53992 Zeilen und 1620 KB Dart-Code und nutzt einige Open-Source-Bibliotheken aus der Community.

Wer hat Quire entwickelt?

Bevor wir mit diesem Projekt begannen, waren wir als Rikulo-Team bekannte Dart-Enthusiasten und hatten bereits mehrere Dart-Bibliotheken veröffentlicht, darunter ein UI-Framework, eine UI-Bibliothek, einen Webserver, einen Messaging-Server und einen Datenbank-Client.

Als Dart 2011 erstmals erschien, waren wir alle von seinem Zukunftspotenzial begeistert und setzten Dart sofort in kleinen Teilen unserer Projekte ein. Schließlich wagten wir uns an eine vollständige Anwendung, die überwiegend aus Dart besteht. Hier möchten wir bescheiden einige unserer Erfahrungen teilen und Ihnen hoffentlich nützliche Einblicke in die Entwicklung mit Dart geben.

Warum hat sich Quire für Dart statt JavaScript entschieden?

Es gibt jede Menge Gründe für Dart. Die wichtigsten für uns sind:

  • Das starke Typsystem von Dart bewahrt uns vor unzähligen kleinen Fehlern. Der Dart Editor, die offizielle IDE, liefert schnelles Feedback zu Typfehlern, Autovervollständigung und erleichtert das Tracing.
  • Wir halten das klassenbasierte Vererbungsmodell für deutlich intuitiver als das prototypbasierte.
  • Mit Dart lässt sich auf Client und Server dieselbe Sprache verwenden, inklusive gemeinsamer Datenmodelle und Codebasis.
  • Dart behebt die meisten Stolperfallen von JavaScript. Perfekt ist Dart dabei nicht, aber es räumt mit 99 % der alten bösen Überraschungen auf.
  • Dart bietet schon heute einige beliebte JavaScript-Harmony-Features: Future (Promise), Arrow Functions usw.
  • Hinter Dart steht ein starkes Team mit vielen hochwertigen offiziellen Bibliotheken und gut strukturierten APIs. Dart entwickelt sich noch weiter, aber die Spezifikation ist bereits recht stabil.
  • Auf dem Server bevorzugen wir das Event-Loop-Modell gegenüber Multithreading.
  • Dart führt beim Kompilieren nach JavaScript Tree Shaking durch. (Siehe unten.)

Dart hat aber auch Nachteile:

  • Die Dart-Community ist viel kleiner als die JavaScript-Community.
  • Die Kommunikation zwischen Dart und JavaScript ist nicht trivial.
  • APIs per Polyfill nachzurüsten ist in einer stark typisierten Sprache schwieriger.
  • Die Performance des Dart Editors ist bei großen Projekten (noch) nicht optimal.

Dank der starken Typunterstützung ist das Programmieren in Dart deutlich zuverlässiger als in JavaScript. Zudem ist Dart weniger umständlich als Java und manchmal (etwa bei Funktionsausdrücken) sogar knapper als reines - - JavaScript. Insgesamt arbeitet es sich mit Dart angenehm, bis auf ein paar Punkte:

  • Final-Felder müssen im Initializer initialisiert werden, also vor dem Konstruktorrumpf.
  • Die Mixin-Spezifikation ist noch recht unausgereift und wird nicht vor 2.0 überarbeitet.
  • Generische Typparameter gibt es nicht für Funktionsdeklarationen, nur für Klassen. (Das würde natürlich auch den Aufwand für den Compiler erhöhen.)

Wie funktioniert Dart auf dem Client?

Solange die Dart VM nicht in Chrome angekommen ist, liefert man sein Produkt in der Regel als nach JavaScript kompilierten Code aus. Es gibt unzählige Sprachen, die nach JavaScript kompilieren, doch Dart bietet einige zusätzliche Vorteile.

  • In der Entwicklung führen wir Dart nativ in Dartium aus, einem Chromium-Fork mit integrierter Dart VM. In dieser Phase müssen wir nicht kompilieren, was uns unzählige Unterbrechungen erspart.
  • Für Tests und Produktion kompilieren wir nach JavaScript und laufen in allen gängigen Browsern. Der Dart-zu-JavaScript-Compiler führt Tree Shaking durch und entfernt ungenutzten Code aus dem Ergebnis. Das reduziert die Größe unseres JavaScript-Codes erheblich.

Warum Dart auf dem Server?

Dart auf dem Server war in der Dart-Community nie ein heißes Thema. Wir halten Dart dennoch für einen starken Kandidaten als serverseitige Programmiersprache, denn:

  • Webdienste arbeiten aufgrund ihrer asynchronen Natur sehr gut mit dem Event-Loop-Modell (statt Multithreading).
  • Serverseitiger Code erfordert deutlich mehr Robustheit und Sicherheit als der Client. Hier ist eine stark typisierte Sprache wirklich Gold wert.

Verwandt: Quire erhält ISO-Zertifizierung zum Schutz Ihrer Daten – derselbe Fokus auf serverseitige Robustheit und Sicherheit zeigt sich Jahre später in Quires formaler Datenschutz-Zertifizierung.

Welche Bibliotheken nutzt Quire in seinem Dart-Stack?

Quire basiert auf rund 30 Bibliotheksimporten. 10 davon stammen aus der Community, der Rest wurde vom Dart-Team veröffentlicht. Als Dart-Experte würden Sie vielleicht AngularDART und Polymer.dart darunter vermuten, doch beide fehlen.

Wir verwenden AngularDART nicht, weil:

  • wir eine feine DOM-Kontrolle möchten.
  • wir die Client-Struktur nach eigenen Architekturrichtlinien gestalten und dieses Paradigma sich von der Angular-Logik unterscheidet.
  • AngularDART zum Zeitpunkt unserer Prüfung einen großen Overhead bei der Größe des kompilierten JavaScript-Codes erzeugte. Das wurde inzwischen jedoch stark verbessert.

Auch Polymer.dart verwenden wir nicht, weil:

  • ShadowDOM aufgrund von Kapselung und Event-Retargeting nicht mit selektororientierten Frameworks wie Bootstrap zusammenarbeiten kann.
  • Styles nicht von außerhalb des ShadowDOM eingeschleust werden können. Basiert ein Komponentenset eines Drittanbieters auf Polymer, ist es für Nutzer nahezu unmöglich, sein Look-and-Feel zu ändern. Update: Seit Dezember 2013 lassen sich interne Styles von außen anpassen. Siehe Shadow DOM 201.

Was sind DQuery und Bootjack?

Die Grundpfeiler unseres clientseitigen Stacks sind DQuery und Bootjack, beides Open-Source-Projekte des Rikulo-Teams:

  • DQuery ist eine teilweise Portierung von jQuery nach Dart mit Fokus auf das Event-Delegation-System von jQuery.
  • Bootjack ist eine vollständige Portierung von Bootstrap 3 mit nahezu identischem CSS und identischen APIs.

So haben wir unseren Anwendungs-Stack aufgebaut, um unser Wissen und unsere Fähigkeiten aus der JavaScript-Welt weiter zu nutzen.

Was ist der Webserver Stream?

Stream ist unser Webserver, geschrieben in reinem Dart und ausgestattet mit Routing, Filtern, serverseitigem MVC und mehr. Stream arbeitet reibungslos mit dem Event-Loop-Modell. Einen Request-Handler zu schreiben heißt einfach, eine Folge nicht blockierender Routinen zu verketten.

Das ist nicht nur produktiver, sondern macht auch mehr Spaß als das klassische Multithreading-Modell. Zusätzlich skalieren wir unseren Webdienst und verarbeiten HTTPS mit nginx, das Anfragen an Stream weiterleitet. Mit dieser Architektur können wir Dart-VMs einzeln starten und beenden und den Server aktualisieren, ohne die Aktivitäten der Nutzer zu unterbrechen.

Fazit

Die Arbeit mit Dart macht uns Freude, und wir freuen uns auf weitere spannende Entwicklungen in der Dart-Community. Und zu guter Letzt: Wenn Sie neugierig sind, was sich mit Dart erreichen lässt, probieren Sie unsere App Quire aus. Sie ist kostenlos!

Lesen Sie mehr darüber, wie Quire später als Mark II neu gedacht und neu gebaut wurde.

Architekturdiagramm von Quire mit der Client-Server-Umsetzung in Dart

Welche Lehren aus dem Build von 2014 gelten 2026 noch?

Sowohl die Sprache Dart als auch die Codebasis von Quire haben sich seit diesem Beitrag stark weiterentwickelt. Dart 2.0 (Sound Type System) erschien 2018, Dart 3.0 (Null Safety, Records, Patterns) 2023, und Flutter hat die plattformübergreifende UI-Landschaft verändert (auch Quires eigenes Mobile-Team ist umgestiegen). Die oben beschriebenen Architekturentscheidungen halten sich jedoch besser, als man erwarten würde.

Starke Typisierung über Client und Server hinweg zahlt sich weiterhin aus. Die Laufzeitfehler, die ein starkes Typsystem beim Build abfängt, sind nach wie vor dieselben. JavaScript hat sich mit TypeScript ein Stück weit in Richtung Typisierung bewegt, doch ein durchgängig typisierter End-to-End-Stack bleibt selten. Die Art von Bugs, die Simon nannte (unzählige kleine Fehler), landet bei einem untypisierten Stack immer noch in der Produktion.

Gemeinsame Datenmodelle für Client und Server sparen weiterhin Arbeit. Das Problem beim Duplizieren von Modellen (eines in JS, eines in Python, die unbemerkt auseinanderdriften) ist 2026 dasselbe wie 2014. Auch die Lösung ist dieselbe: eine Sprache durchgängig. Genau deshalb bauen TypeScript-on-Node-Teams Architekturen im Stil von Quire.

Event Loop schlägt Multithreading bei Webservern weiterhin. Node, Deno, Bun und Darts eigenes Stream-Muster sind sich hier einig. Die Debatte flammt alle paar Jahre neu auf und endet jedes Mal am selben Punkt.

Tree Shaking ist wichtiger denn je. 2014 war Darts Tree-Shaking-Compiler ein Alleinstellungsmerkmal. 2026 ist es Standard für jede Build-Pipeline mit JS-Ziel. Webpack, Rollup, esbuild und Vite beherrschen es alle. Die Lehre gilt weiter, die Tools haben aufgeholt.

Die ShadowDOM-Bedenken von 2014 haben sich größtenteils erledigt. Polymer.dart wurde eingestellt, Web Components sind ausgereift. Die Gründe, die Simon gegen Polymer anführte (Style-Injection, Zusammenarbeit mit Frameworks), hat die Plattform schließlich gelöst. Das allgemeine Prinzip (keine Bleeding-Edge-Frameworks für den Kern einer Produktions-App) gilt 2026 weiterhin für das jeweils aktuelle „spannende" Framework.

Verwandt: How It's Made: Eine Flutter-basierte mobile Timeline – ein Blick darauf, wie Quires Mobile-Team mit Flutter eine Timeline-Ansicht gebaut hat.

Was sind die häufigsten Fehler bei der Sprachwahl für eine große Web-App?

Die Wahl des Sprach-Stacks für eine Anwendung, die über Jahre laufen soll, gehört zu den wenigen technischen Entscheidungen, die sich nur teuer rückgängig machen lassen. Vier Muster tauchen immer wieder auf, wenn Teams danebenliegen.

1. Standardmäßig die Sprache mit der größten Community wählen. JavaScript hat die größte Community, aber „am größten" heißt nicht „am besten für Ihr Problem geeignet". Eine Sprache mit starkem Typsystem, guten Tools und kleinerer Community kann ein ausuferndes Ökosystem mit schwachen Garantien übertreffen. Die Größe der Community zählt, aber sie ist nicht das Einzige, was zählt.

2. Einen Stack wählen, der Client- und Server-Sprache trennt. Jedes duplizierte Datenmodell ist ein Bug, der nur darauf wartet, aufzutreten. Teams mit Ruby auf dem Server und JS auf dem Client tragen diese Kosten für immer. Teams, die eine Sprache für beide Seiten nutzen (Dart, TypeScript, Kotlin), vermeiden eine ganze Fehlerklasse.

3. Auf die neueste Technik setzen, bevor sie sich stabilisiert hat. Das Quire-Team verzichtete 2014 auf AngularDART und Polymer.dart, weil bei beiden grundlegende Architekturfragen offen waren. AngularDART schlug einen radikal neuen Kurs ein, Polymer wurde eingestellt. Die allgemeine Regel (ein Framework soll sich erst in großem Maßstab in der Produktion bewähren, bevor Sie den Kern Ihrer App darauf aufbauen) gilt 2026 weiterhin für das jeweils aktuelle „spannende" Framework.

4. Für kurzfristiges Tempo auf das Typsystem verzichten. Untypisierte Sprachen fühlen sich in der ersten Woche schneller an. Nach sechs Monaten ist die gesparte Zeit beim Debugging mehr als aufgebraucht. Entwicklungsteams, die sowohl untypisierte als auch typisierte Stacks in großem Maßstab erlebt haben, kehren so gut wie nie freiwillig zurück.

Die Wette des Quire-Teams auf Dart im Jahr 2014 wirkt im Rückblick vernünftig. Nicht weil Dart dominant wurde (das wurde es nicht), sondern weil die zugrunde liegenden Kriterien (typisiert, gemeinsamer Code für Client und Server, Event Loop, Tree Shaking) im folgenden Jahrzehnt zum Branchenkonsens wurden.

Gut gealtert sind die zugrunde liegenden Engineering-Prinzipien, nicht die konkreten Tool-Entscheidungen. Dieses Muster gilt meist für jede Sprachwahl unter Unsicherheit: Wählen Sie nach Prinzipien, die Sie auch in zehn Jahren noch vertreten können, nicht nach Popularität, die Sie heute messen können.

Schließen Sie sich über 100.000 Teams an, die die Projektmanagement-Software Quire nutzen – kostenlos registrieren

Häufig gestellte Fragen

In welcher Sprache ist Quire geschrieben?

In Dart, sowohl auf dem Client als auch auf dem Server. Die Anwendung umfasst rund 54.000 Zeilen Dart-Code mit etwa 30 Bibliotheksimporten.

Warum hat sich Quire für Dart statt JavaScript oder TypeScript entschieden?

Wegen der starken Typisierung, des klassenbasierten Vererbungsmodells und einer einzigen Sprache für Client und Server. Außerdem bot Dart einige moderne Features, bevor JavaScript sie breit unterstützte.

Warum hat Quire nicht AngularDART oder Polymer.dart verwendet?

Das Team wollte eine feinere DOM-Kontrolle, als das Binding von AngularDART erlaubte, und Quires Architekturmuster passten nicht zur Logik von Angular. Auf Polymer.dart verzichtete das Team, weil ShadowDOM damals mit Selektoren im Bootstrap-Stil kollidierte. Polymer wurde später eingestellt, was die Entscheidung bestätigte.

Was sind DQuery und Bootjack?

Open-Source-Bibliotheken des Rikulo-Teams (Quires Entwicklungsteam). DQuery ist eine teilweise Portierung von jQuery nach Dart mit Fokus auf Event Delegation. Bootjack ist eine vollständige Portierung von Bootstrap 3 mit nahezu identischem CSS und identischen APIs.

Was ist Stream im Quire-Stack?

Quires Webserver, geschrieben in reinem Dart und basierend auf dem Event-Loop-Modell. Routing, Filter und serverseitiges MVC sind integriert. Quire betreibt Stream hinter nginx, das Skalierung und HTTPS übernimmt.

Simon Pai
Co-Founder at Bookshow