Premiers pas avec Loco, la réponse de Rust à Rails
Créez une application web Rust avec Loco, le framework inspiré de Rails. Installez la CLI, générez une API CRUD et ajoutez un worker avec Loco 1.2.
Loco est un framework web Rust inspiré de Rails. Il regroupe le routage Axum, les modèles et migrations Sea-ORM, les workers d’arrière-plan et les générateurs de code derrière une seule commande cargo loco.
Si vous avez déjà passé un week-end à assembler Axum, un ORM, un outil de migration et une file de tâches avant d’écrire la moindre ligne de logique métier, Loco est conçu pour vous épargner ce travail. Ce guide installe Loco, crée une application API, génère une ressource via un scaffold et ajoute une tâche en arrière-plan. De nombreux tutoriels plus anciens ciblent des versions antérieures à la 1.0 ; toutes les commandes ci-dessous utilisent donc la CLI 1.x de Loco 1.2.0. Si vous découvrez le langage, commencez par les bases de Rust.
Points clés
- Loco est un framework web Rust calqué sur Ruby on Rails. Il s’appuie sur Axum pour le routage et sur Sea-ORM 2.0 pour les modèles et les migrations.
- Installez la CLI avec
cargo install loco. Vous aurez aussi besoin decargo install sea-orm-cli, mais uniquement si votre application utilise une base de données. - Dans Loco 1.2,
cargo loco generate scaffoldgénère une migration, un modèle, une entité, des DTO et un contrôleur CRUD, puis applique la migration. Aucune étape de migration distincte n’est nécessaire. - Le serveur de développement d’une nouvelle application Loco écoute sur le port 5150.
- En développement, les tâches en arrière-plan s’exécutent dans le même processus en mode
BackgroundAsync. En production, on les bascule généralement vers une file Redis, Postgres ou SQLite traitée parcargo loco start --worker.
Qu’est-ce que Loco en Rust ?
Loco est un framework Rust full-stack et opinionné. Il prend en charge les choix d’architecture qu’un projet Axum nu vous laisse faire. La page d’accueil de Loco indique Axum comme couche HTTP et Sea-ORM 2.0 comme ORM. Les workers, un planificateur, l’envoi d’e-mails, le stockage et la mise en cache sont également intégrés. Vous disposez d’une seule structure de projet, d’un seul système de configuration et d’une seule CLI : inutile de choisir cinq crates et d’écrire le code qui les relie. Le code source est disponible sur GitHub. Loco a atteint sa première version stable, la 1.0, en juillet 2026.
Quelles idées de Rails Loco reprend-il ?
Loco reprend quatre habitudes de Rails : chaque projet suit la même structure prévisible, les générateurs écrivent le code répétitif, les modifications de schéma passent par des migrations versionnées et les traitements lents sont confiés à des tâches en arrière-plan. Si vous connaissez Django ou Laravel, vous avez déjà rencontré ces mêmes idées sous d’autres noms.
| Concept | Signification | Commande ou emplacement dans Loco 1.2 |
|---|---|---|
| Convention plutôt que configuration | Les fichiers se trouvent là où le framework les attend | Structure générée sous src/ et config/ |
| Générateurs | La CLI écrit le code répétitif | cargo loco generate scaffold, model, controller, worker |
| Migrations | Modifications de schéma versionnées | migration/src/, appliquées automatiquement lors de la génération |
| Tâches en arrière-plan | Le traitement s’exécute en dehors du cycle de requête | cargo loco generate worker, perform_later |
Comment installer Loco et créer une application ?
L’installation de Loco se fait en deux commandes cargo, et la création d’une application en une de plus. Comme le précise le README de Loco, l’installation de sea-orm-cli n’est nécessaire que si votre application utilise une base de données. Cet exemple utilise SQLite, vous en aurez donc besoin :
cargo install loco
cargo install sea-orm-cli
Générez ensuite l’application. Si vous passez les quatre options, l’assistant ignore ses questions interactives : la commande peut ainsi être scriptée et produit toujours le même résultat :
loco new --name tour_app --db sqlite --bg async --assets none
cd tour_app
cargo loco start
D’après le tutoriel officiel de première application, --db sqlite sélectionne SQLite comme base de données, --bg async exécute les tâches en arrière-plan dans le même processus et --assets none ignore la génération des vues, de sorte que l’application ne sert que du JSON. La dernière ligne de la sortie de démarrage confirme que le serveur est opérationnel :
listening on port 5150
Par défaut, le serveur de développement écoute sur le port 5150. Les fichiers de configuration définissent le port via un appel get_env qui lit la variable d’environnement PORT, comme indiqué dans la référence de configuration ; vous pouvez donc le modifier à cet endroit. Comme vous avez choisi une base de données, l’application inclut aussi des routes d’authentification intégrées sous /api/auth/*.
Les tutoriels plus anciens installent une crate nommée loco-cli. Loco 1.0 a supprimé cette crate : la CLI s’installe désormais sous le nom loco.
Comment générer une ressource avec un scaffold ?
Un scaffold Loco produit une API CRUD fonctionnelle et adossée à une base de données en une seule commande :
cargo loco generate scaffold posts title:string! content:text --no-auth
Dans Loco 1.2, cargo loco generate scaffold génère une migration, un modèle et une entité Sea-ORM, des DTO typés pour les requêtes et les réponses, ainsi qu’un contrôleur CRUD. La commande applique ensuite la migration et régénère les entités : vous n’avez jamais à lancer de commande de migration séparée.
La syntaxe des champs provient du guide d’ajout d’un modèle. Un type se terminant par !, comme title:string!, crée une colonne obligatoire. Un type seul comme content:text crée une colonne pouvant être nulle, et ^ marque un champ comme unique. Par défaut, les routes générées attendent un JWT : une requête anonyme renvoie donc une erreur 401. L’option --no-auth rend les routes publiques, ce qui simplifie cette démonstration.
Voici les parties du projet généré utilisées dans ce guide (vue partielle) :
tour_app/
├── config/development.yaml
├── migration/src/
└── src/
├── app.rs
├── controllers/posts.rs
├── dtos/
├── models/_entities/
└── workers/
Pour tester le nouvel endpoint, redémarrez le serveur et envoyez une requête POST :
curl -X POST -H "Content-Type: application/json" \
-d '{"title":"Tour post","content":"hi"}' localhost:5150/api/posts
La réponse JSON commence par {"id":1, puis renvoie le contenu de l’article enregistré.
Comment ajouter une tâche en arrière-plan dans Loco ?
Une tâche en arrière-plan Loco est un module worker doté d’une struct d’arguments typée. On la met en file d’attente avec perform_later. Générez-en une :
cargo loco generate worker notifier
added: "src/workers/notifier.rs"
injected: "src/workers/mod.rs"
injected: "src/app.rs"
Comme l’explique le guide des workers d’arrière-plan, le générateur nomme toujours la struct Worker et la place dans son propre module, à côté d’une struct WorkerArgs vide que vous complétez. Le worker notifier généré est donc workers::notifier::Worker. Dans src/workers/notifier.rs, ajoutez un champ à WorkerArgs et remplacez le corps de perform. Laissez build et le reste du fichier généré tels quels :
#[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(())
}
Ouvrez ensuite src/controllers/posts.rs et ajoutez ces lignes dans le handler create généré, juste après la ligne qui insère le nouvel article (let item = item.insert(&ctx.db).await?;). Depuis Loco 1.0, les clés primaires générées sont de type i64 : item.id correspond donc à post_id sans conversion :
crate::workers::notifier::Worker::perform_later(
&ctx,
crate::workers::notifier::WorkerArgs { post_id: item.id },
)
.await?;
Depuis Loco 1.0, perform_later() renvoie l’identifiant de la tâche sous la forme d’un Result<String>, comme l’indiquent les notes de version de Loco 1.0. Vous pouvez le journaliser si vous souhaitez tracer les tâches par la suite.
Votre fichier config/development.yaml définit workers.mode sur BackgroundAsync, qui exécute les tâches sous forme de tâches Tokio dans le même processus. Le mode BackgroundAsync ne nécessite aucun backend de file d’attente. En production, passez workers.mode à BackgroundQueue, configurez une file Redis, Postgres ou SQLite, et traitez les tâches dans un processus séparé avec cargo loco start --worker. Les files Postgres et SQLite fonctionnent avec la feature worker par défaut, tandis qu’une file Redis nécessite worker_redis ; le backend se sélectionne dans la configuration via queue.kind. Le code de votre worker et de votre contrôleur reste inchangé lors de ce changement.
À qui s’adresse Loco ?
Loco accélère considérablement la mise en place d’un backend Rust, mais il ne supprime pas les contraintes inhérentes à l’écriture de code Rust :
- Temps de compilation. Chaque modification passe par
rustc: la boucle modification-rechargement est donc plus lente qu’avec les frameworks Ruby, Python ou PHP. - Écosystème. Les intégrations tierces, plugins et questions résolues sont bien moins nombreux que ceux accumulés par Rails ou Django.
- Courbe d’apprentissage. Le code généré suppose toujours que vous maîtrisez l’ownership, l’asynchrone et les traits, et les erreurs du compilateur dans les handlers supposent que vous savez les lire.
Loco convient bien aux développeurs qui connaissent déjà Rust et veulent la rapidité de mise en place de Rails, ainsi qu’aux développeurs Rails, Django ou Laravel qui passent délibérément à Rust. C’est en revanche un mauvais choix pour un premier backend si vous apprenez en même temps les serveurs web et Rust. Si vous vous demandez encore si Rust vaut la peine d’être appris pour le développement web, lisez si les développeurs web ont besoin de Rust.
Conclusion
Loco offre aux développeurs Rust ce que Rails offre aux développeurs Ruby : une seule CLI, une structure prévisible et des migrations et tâches intégrées, le tout reposant sur Axum et Sea-ORM. Utilisez les commandes 1.x de ce guide plutôt que celles, antérieures à la 1.0, des anciens tutoriels. Prochaine étape : ajoutez une deuxième ressource avec cargo loco generate model, puis suivez le guide des workers d’arrière-plan pour faire passer votre file d’attente de BackgroundAsync à un backend persistant.
FAQ
Puis-je utiliser des middlewares et des extracteurs Axum existants dans une application Loco ?
Oui. Loco est essentiellement une couche d'assemblage autour d'Axum : les extracteurs personnalisés qui implémentent FromRequestParts fonctionnent donc dans les contrôleurs Loco. Pour ajouter des layers Tower, comme un timeout tower-http ou une couche de session, implémentez Hooks::after_routes dans src/app.rs, qui reçoit le routeur Axum déjà construit par Loco.
Comment faire passer une application Loco de SQLite à Postgres ?
Définissez database.uri dans config/development.yaml ou config/production.yaml avec une chaîne de connexion postgres://. La configuration générée lit cette valeur via get_env avec la variable DATABASE_URL : définir cette variable d'environnement fonctionne donc également. Par défaut, Loco attend l'utilisateur loco, le mot de passe loco et une base de données nommée d'après l'application et l'environnement, par exemple myapp_development. Ajouter sslmode=require à l'URI active TLS pour Postgres, sans feature Cargo supplémentaire.
Comment déployer une application Loco en production ?
Compilez un binaire de release avec cargo build --release et copiez-le sur le serveur avec le dossier config/. La machine cible n'a besoin ni de la toolchain Rust ni de cargo. Pour le packaging, cargo loco generate deployment propose trois types : docker, nginx et lambda. Docker génère un Dockerfile et un .dockerignore, nginx génère une configuration de reverse proxy, et lambda génère un point d'entrée AWS Lambda et ajoute la dépendance lambda_http. Les paramètres de production se trouvent dans config/production.yaml.
Quelle est la différence entre le planificateur et les workers d'arrière-plan de Loco ?
Les workers exécutent les tâches que votre code met en file d'attente avec perform_later, tandis que le planificateur exécute des tâches selon un calendrier. Les tâches du planificateur se déclarent dans le fichier YAML de configuration, chacune avec une expression cron ou une planification en anglais courant. La valeur run désigne une tâche Loco enregistrée, ou une commande shell lorsque shell vaut true. L'option --scheduler exécute le planificateur en parallèle du serveur, sans processus worker.
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