Zum Inhalt

Flutter & Dart Frog

KanjiIQ verwendet Flutter für das Frontend und Dart Frog für das Backend — ein einheitliches Dart-Ökosystem, das Entwicklung, Testen und Deployment vereinfacht.

Flutter Web

Warum Flutter?

  • Eine einzige Codebasis: Web, iOS, Android und Desktop aus einer Quelle
  • Material Design 3: Nativ wirkende Benutzeroberfläche mit minimalem individuellem Styling
  • Starke i18n-Unterstützung: Eingebaute ARB-basierte Lokalisierung für 51 Sprachen
  • Offline-Unterstützung: SQLite über das sqflite-Paket für lokales Daten-Caching

Build-Prozess

Flutter Web erzeugt statische Assets (HTML, JS, CSS, Bilder), die von Nginx bereitgestellt werden:

# From Dockerfile.frontend (simplified)
FROM ubuntu:22.04 AS builder
# Install Flutter SDK
RUN flutter gen-l10n          # Generate 51 localization files
RUN flutter build web --release

FROM nginx:alpine
COPY --from=builder /app/frontend/build/web /usr/share/nginx/html

Build-Argumente:

  • API_URL — Backend API-Endpunkt (Standard: relativer /api/)
  • CACHEBUST — Erzwingt frische Builds in CI/CD (zeitstempelbasiert)

Zustandsverwaltung

KanjiIQ verwendet Provider für die Zustandsverwaltung:

MultiProvider(
  providers: [
    ChangeNotifierProvider(create: (_) => StudyProvider()),
    // Locale, connectivity, sync providers
  ],
  child: MyApp(),
)

Provider wurde gegenüber Alternativen (Riverpod, BLoC) wegen seiner Einfachheit gewählt — die Zustandsanforderungen von KanjiIQ sind unkompliziert (Karteikarten-Sitzungszustand, Locale-Einstellungen, Verbindungsstatus).

Routing

GoRouter übernimmt deklaratives Routing mit Unterstützung für:

  • Deep Linking (URL-basierte Navigation)
  • Redirect-Guards (Authentifizierungsprüfungen)
  • Verschachtelte Routen für Bildschirmhierarchie

Dart Frog Backend

Warum Dart Frog?

  • Gleiche Sprache wie das Frontend: Dart-Modelle können geteilt werden
  • Leichtgewichtig: Minimaler Framework-Overhead, ähnlich wie Express.js
  • Middleware-basiert: Saubere Anfrage-Pipeline mit komponierbarer Middleware
  • Hot Reload: Schnelle Entwicklungsiteration mit dart_frog dev

Anfrage-Lebenszyklus

graph LR
    R[HTTP Request] --> MW[Middleware Stack]
    MW --> RH[Route Handler]
    RH --> DB[(PostgreSQL)]
    DB --> RH
    RH --> RS[JSON Response]

Jede Route ist eine Dart-Datei im routes/-Verzeichnis. Dart Frog verwendet dateibasiertes Routing:

backend/routes/
├── _middleware.dart           # Global middleware
├── api/v1/
│   ├── kanji/
│   │   ├── index.dart         # GET /api/v1/kanji
│   │   ├── [id].dart          # GET /api/v1/kanji/:id
│   │   └── random/
│   │       └── index.dart     # GET /api/v1/kanji/random
│   └── admin/
│       ├── _middleware.dart    # Admin auth middleware
│       └── ...

Build-Prozess

# From Dockerfile.backend (simplified)
FROM dart:stable AS builder
RUN dart pub global activate dart_frog_cli
RUN dart_frog build

FROM dart:stable
COPY --from=builder /app/build /app
CMD ["./server"]

Der Build-Schritt kompiliert Dart zu einer eigenständigen Server-Binary mit allen vorregistrierten Routen.

Gemeinsames Dart-Ökosystem

Sowohl Frontend als auch Backend profitieren vom selben Dart-Tooling:

Werkzeug Zweck
dart analyze Statische Analyse über beide Codebasen
dart format Einheitlicher Code-Stil
dart test Unit- und Integrationstests
pub.dev Gemeinsames Paket-Repository

Mobile Bereitschaft

Das Flutter-Frontend ist für Multi-Plattform-Deployment konzipiert:

  • Web: Derzeit bereitgestellt (primäres Ziel)
  • iOS/Android: Build-bereit mit flutter build apk / flutter build ipa
  • Desktop: Unterstützt über flutter build macos / linux / windows

Die Offline-First-Architektur (SQLite-Cache, Konnektivitätserkennung, Hintergrundsynchronisation) wurde von Anfang an mit Mobilgeräten im Blick entwickelt.