12k
All articles

Erste Schritte mit Loco, Rusts Antwort auf Rails

Erstellen Sie eine Rust-Web-App mit Loco, dem von Rails inspirierten Framework. Installieren Sie die CLI, generieren Sie eine CRUD-API und ergänzen Sie einen Hintergrund-Worker mit Loco 1.2.

OpenReplay Team
OpenReplay Team
Erste Schritte mit Loco, Rusts Antwort auf Rails

Loco ist ein von Rails inspiriertes Web-Framework für Rust. Es bündelt Axum-Routing, Sea-ORM-Modelle und -Migrationen, Background-Worker und Code-Generatoren hinter einem einzigen cargo loco-Befehl.

Falls Sie schon einmal ein ganzes Wochenende damit verbracht haben, Axum, ein ORM, einen Migration-Runner und eine Job-Queue miteinander zu verbinden, bevor Sie auch nur eine Zeile Geschäftslogik geschrieben haben, dann soll Ihnen Loco genau diese Arbeit abnehmen. Diese Anleitung zeigt, wie Sie Loco installieren, eine API-App erstellen, eine Ressource per Scaffold generieren und einen Background-Job hinzufügen. Viele ältere Tutorials beziehen sich auf Versionen vor 1.0. Deshalb verwenden alle folgenden Befehle die 1.x-CLI aus Loco 1.2.0. Wenn Sie neu in der Sprache sind, beginnen Sie mit den Rust-Grundlagen.

Das Wichtigste in Kürze

  • Loco ist ein Rust-Web-Framework nach dem Vorbild von Ruby on Rails. Es baut auf Axum für das Routing und Sea-ORM 2.0 für Modelle und Migrationen auf.
  • Installieren Sie die CLI mit cargo install loco. Zusätzlich benötigen Sie cargo install sea-orm-cli, allerdings nur, wenn Ihre App eine Datenbank verwendet.
  • In Loco 1.2 erzeugt cargo loco generate scaffold eine Migration, ein Model, eine Entity, DTOs und einen CRUD-Controller und wendet anschließend die Migration an. Ein separater Migrationsschritt entfällt.
  • Der Entwicklungsserver einer neuen Loco-App lauscht auf Port 5150.
  • Background-Jobs laufen während der Entwicklung im BackgroundAsync-Modus innerhalb des Prozesses. Für die Produktion verlagert man sie typischerweise in eine Redis-, Postgres- oder SQLite-Queue, die von cargo loco start --worker abgearbeitet wird.

Was ist Loco in Rust?

Loco ist ein meinungsstarkes („opinionated“) Full-Stack-Framework für Rust. Es übernimmt die Entscheidungen zum Stack, die Ihnen ein reines Axum-Projekt selbst überlässt. Die Loco-Homepage nennt Axum als HTTP-Schicht und Sea-ORM 2.0 als ORM. Worker, ein Scheduler, Mailer, Storage und Caching sind ebenfalls integriert. Sie erhalten eine einheitliche Projektstruktur, ein Konfigurationssystem und eine CLI und müssen daher nicht fünf Crates auswählen und den Code schreiben, der sie miteinander verbindet. Der Quellcode liegt auf GitHub. Loco erreichte im Juli 2026 sein erstes stabiles Release, 1.0.

Welche Rails-Konzepte übernimmt Loco?

Loco übernimmt vier Rails-Gepflogenheiten: Jedes Projekt hat dieselbe vorhersehbare Struktur, Generatoren schreiben den Boilerplate-Code, Schemaänderungen erfolgen über versionierte Migrationen, und langsame Aufgaben werden in Background-Jobs ausgelagert. Wer Django oder Laravel kennt, ist denselben Konzepten bereits unter anderen Namen begegnet.

KonzeptBedeutungBefehl oder Ort in Loco 1.2
Convention over ConfigurationDateien liegen dort, wo das Framework sie erwartetGenerierte Struktur unter src/ und config/
GeneratorenDie CLI schreibt Boilerplate-Codecargo loco generate scaffold, model, controller, worker
MigrationenVersionierte Schemaänderungenmigration/src/, werden beim Generieren automatisch angewendet
Background-JobsAufgaben laufen außerhalb des Request-Zykluscargo loco generate worker, perform_later

Wie installiert man Loco und erstellt eine App?

Die Installation von Loco erfordert zwei Cargo-Befehle, das Erstellen einer App einen weiteren. Wie in der Loco-README erläutert, wird sea-orm-cli nur benötigt, wenn Ihre App eine Datenbank verwendet. Dieses Beispiel nutzt SQLite, daher brauchen Sie es:

cargo install loco
cargo install sea-orm-cli

Generieren Sie als Nächstes die App. Wenn Sie alle vier Flags übergeben, überspringt der Assistent seine Abfragen. Der Befehl lässt sich so skripten und liefert jedes Mal dasselbe Ergebnis:

loco new --name tour_app --db sqlite --bg async --assets none
cd tour_app
cargo loco start

Laut dem offiziellen Tutorial zur ersten App wählt --db sqlite SQLite als Datenbank, --bg async führt Background-Jobs innerhalb des Prozesses aus, und --assets none überspringt das Scaffolding von Views, sodass die App ausschließlich JSON ausliefert. Die letzte Zeile der Startausgabe bestätigt, dass der Server läuft:

listening on port 5150

Standardmäßig lauscht der Entwicklungsserver auf Port 5150. Die Konfigurationsdateien setzen den Port über einen get_env-Aufruf, der die Umgebungsvariable PORT ausliest, wie in der Konfigurationsreferenz beschrieben. Dort können Sie ihn also ändern. Da Sie eine Datenbank gewählt haben, bringt die App außerdem integrierte Auth-Routen unter /api/auth/* mit.

Ältere Tutorials installieren ein Crate namens loco-cli. Mit Loco 1.0 wurde dieses Crate entfernt, und die CLI wird jetzt als loco installiert.

Wie generiert man eine Ressource per Scaffold?

Ein Loco-Scaffold erzeugt mit einem einzigen Befehl eine funktionsfähige, datenbankgestützte CRUD-API:

cargo loco generate scaffold posts title:string! content:text --no-auth

In Loco 1.2 erzeugt cargo loco generate scaffold eine Migration, ein Sea-ORM-Model samt Entity, typisierte Request- und Response-DTOs sowie einen CRUD-Controller. Anschließend wendet es die Migration an und generiert die Entities neu, sodass Sie nie einen separaten Migrationsbefehl ausführen müssen.

Die Feldsyntax stammt aus dem Leitfaden zum Hinzufügen eines Models. Ein Typ mit abschließendem !, etwa title:string!, ergibt eine Pflichtspalte. Ein Typ ohne Zusatz wie content:text ergibt eine nullable Spalte, und ^ kennzeichnet ein Feld als eindeutig (unique). Per Scaffold erzeugte Routen erwarten standardmäßig ein JWT, sodass eine anonyme Anfrage 401 zurückgibt. Das Flag --no-auth macht die Routen öffentlich, was diese Demo einfach hält.

Die in dieser Anleitung verwendeten Teile des generierten Projekts (Ausschnitt):

tour_app/
├── config/development.yaml
├── migration/src/
└── src/
    ├── app.rs
    ├── controllers/posts.rs
    ├── dtos/
    ├── models/_entities/
    └── workers/

Um den neuen Endpunkt zu testen, starten Sie den Server neu und senden einen POST-Request:

curl -X POST -H "Content-Type: application/json" \
  -d '{"title":"Tour post","content":"hi"}' localhost:5150/api/posts

Die JSON-Antwort beginnt mit {"id":1, und gibt anschließend den gespeicherten Post zurück.

Wie fügt man in Loco einen Background-Job hinzu?

Ein Background-Job in Loco ist ein Worker-Modul mit einem typisierten Argument-Struct. Sie reihen ihn mit perform_later in die Queue ein. Generieren Sie einen Worker:

cargo loco generate worker notifier
added: "src/workers/notifier.rs"
injected: "src/workers/mod.rs"
injected: "src/app.rs"

Wie der Leitfaden zu Background-Workern erklärt, nennt der Generator das Struct immer Worker und legt es in einem eigenen Modul ab, neben einem leeren WorkerArgs-Struct, das Sie selbst befüllen. Der generierte Notifier-Worker heißt also workers::notifier::Worker. Fügen Sie in src/workers/notifier.rs ein Feld zu WorkerArgs hinzu und ersetzen Sie den Rumpf von perform. Lassen Sie build und den Rest der generierten Datei unverändert:

#[derive(Deserialize, Debug, Serialize)]
pub struct WorkerArgs {
    pub post_id: i64,
}

// inside the generated `impl BackgroundWorker<WorkerArgs> for Worker`
async fn perform(&self, args: WorkerArgs) -> Result<()> {
    println!("new post created: {}", args.post_id);
    Ok(())
}

Öffnen Sie anschließend src/controllers/posts.rs und fügen Sie die folgenden Zeilen in den per Scaffold erzeugten create-Handler ein, direkt nach der Zeile, die den neuen Post einfügt (let item = item.insert(&ctx.db).await?;). Seit Loco 1.0 sind generierte Primärschlüssel vom Typ i64, sodass item.id ohne Konvertierung zu post_id passt:

crate::workers::notifier::Worker::perform_later(
    &ctx,
    crate::workers::notifier::WorkerArgs { post_id: item.id },
)
.await?;

Seit Loco 1.0 gibt perform_later() die Job-ID als Result<String> zurück, wie in den Release Notes zu Loco 1.0 aufgeführt. Sie können sie loggen, wenn Sie Jobs später nachverfolgen möchten.

Ihre config/development.yaml setzt workers.mode auf BackgroundAsync, wodurch Jobs als Tokio-Tasks innerhalb des Prozesses ausgeführt werden. Der BackgroundAsync-Modus benötigt überhaupt kein Queue-Backend. Für die Produktion stellen Sie workers.mode auf BackgroundQueue um, konfigurieren eine Redis-, Postgres- oder SQLite-Queue und verarbeiten die Jobs in einem separaten Prozess mit cargo loco start --worker. Postgres- und SQLite-Queues funktionieren mit dem Standard-Feature worker, während eine Redis-Queue worker_redis benötigt. Das Backend wird in der Konfiguration über queue.kind ausgewählt. Ihr Worker- und Controller-Code bleibt beim Wechsel unverändert.

Für wen eignet sich Loco?

Loco beschleunigt die Einrichtung eines Rust-Backends erheblich, beseitigt aber nicht die Kosten, die das Schreiben von Rust mit sich bringt:

  • Kompilierzeiten. Jede Änderung durchläuft rustc, daher ist der Zyklus aus Bearbeiten und Neuladen langsamer als bei Ruby-, Python- oder PHP-Frameworks.
  • Ökosystem. Es gibt deutlich weniger Integrationen von Drittanbietern, Plugins und beantwortete Fragen, als Rails oder Django über die Jahre angesammelt haben.
  • Lernkurve. Auch generierter Code setzt voraus, dass Sie mit Ownership, Async und Traits vertraut sind, und Compilerfehler in Handlern setzen voraus, dass Sie diese lesen können.

Loco eignet sich gut für Entwicklerinnen und Entwickler, die Rust bereits beherrschen und die Einrichtungsgeschwindigkeit von Rails wollen, sowie für Rails-, Django- oder Laravel-Entwickler, die bewusst zu Rust wechseln. Als erstes Backend ist es dagegen eine schlechte Wahl, wenn Sie Webserver und Rust gleichzeitig lernen. Falls Sie noch überlegen, ob sich Rust für die Webentwicklung lohnt, lesen Sie ob Webentwickler Rust brauchen.

Fazit

Loco bietet Rust-Entwicklern das, was Rails Ruby-Entwicklern bietet: eine CLI, eine vorhersehbare Projektstruktur sowie integrierte Migrationen und Jobs, alles auf Basis von Axum und Sea-ORM. Verwenden Sie die 1.x-Befehle aus dieser Anleitung statt der Befehle aus älteren Tutorials vor Version 1.0. Fügen Sie als Nächstes mit cargo loco generate model eine zweite Ressource hinzu und arbeiten Sie dann den Leitfaden zu Background-Workern durch, um Ihre Queue von BackgroundAsync auf ein persistentes Backend umzustellen.

FAQs

Kann ich bestehende Axum-Middleware und -Extractors in einer Loco-App verwenden?

Ja. Loco ist im Wesentlichen Glue-Code rund um Axum, daher funktionieren eigene Extractors, die FromRequestParts implementieren, auch in Loco-Controllern. Um Tower-Layer wie einen tower-http-Timeout oder einen Session-Layer einzubinden, implementieren Sie Hooks::after_routes in src/app.rs. Diese Methode erhält den Axum-Router, den Loco bereits aufgebaut hat.

Wie stelle ich eine Loco-App von SQLite auf Postgres um?

Setzen Sie database.uri in config/development.yaml oder config/production.yaml auf einen postgres://-Connection-String. Die generierte Konfiguration liest den Wert über get_env mit der Variable DATABASE_URL aus, daher funktioniert auch das Setzen dieser Umgebungsvariable. Die Standardwerte von Loco erwarten den Benutzer loco, das Passwort loco und eine Datenbank, die nach App und Umgebung benannt ist, etwa myapp_development. Durch Anhängen von sslmode=require an die URI wird TLS für Postgres aktiviert, ohne dass ein zusätzliches Cargo-Feature nötig ist.

Wie deploye ich eine Loco-App in die Produktion?

Erstellen Sie mit cargo build --release ein Release-Binary und kopieren Sie es zusammen mit dem Ordner config/ auf den Server. Auf dem Zielsystem werden weder eine Rust-Toolchain noch cargo benötigt. Für das Packaging bietet cargo loco generate deployment drei Varianten: docker, nginx und lambda. Docker erzeugt ein Dockerfile und eine .dockerignore, nginx erzeugt eine Reverse-Proxy-Konfiguration, und lambda erzeugt einen AWS-Lambda-Einstiegspunkt und fügt die Abhängigkeit lambda_http hinzu. Die Produktionseinstellungen liegen in config/production.yaml.

Was ist der Unterschied zwischen dem Scheduler und den Background-Workern von Loco?

Worker führen Jobs aus, die Ihr Code mit perform_later in die Queue einreiht, während der Scheduler Jobs nach einem Zeitplan ausführt. Scheduler-Jobs deklarieren Sie in der YAML-Konfiguration, jeweils mit einem Cron-Ausdruck oder einem Zeitplan in natürlicher englischer Sprache. Der Wert von run benennt einen registrierten Loco-Task oder, wenn shell auf true gesetzt ist, einen Shell-Befehl. Mit dem Flag --scheduler läuft der Scheduler parallel zum Server, ohne dass ein Worker-Prozess benötigt wird.

DevTools for the frontend

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.