feat(scaffold): add Axum + Leptos SSR base structure
Sets up the full project skeleton: Cargo.toml with ssr/hydrate features, Axum server entry point, shared Leptos lib, root App component with router, server/client module split, and Trunk config for WASM build. Both `cargo check --features ssr` and `cargo check --features hydrate --target wasm32-unknown-unknown` pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
87
src/main.rs
87
src/main.rs
@@ -1,3 +1,86 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
// main.rs — Point d'entrée du serveur Axum
|
||||
//
|
||||
// Ce fichier est compilé UNIQUEMENT en mode "ssr" (Server-Side Rendering).
|
||||
// `#[cfg(feature = "ssr")]` est l'équivalent d'un `#ifdef` en C :
|
||||
// le code qu'il protège n'existe pas dans le bundle WASM.
|
||||
//
|
||||
// Pour lancer le serveur :
|
||||
// cargo run --features ssr
|
||||
//
|
||||
// Pour lancer avec des logs détaillés :
|
||||
// RUST_LOG=debug cargo run --features ssr
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
#[tokio::main]
|
||||
// `#[tokio::main]` est une macro qui transforme notre `fn main()` synchrone
|
||||
// en une fonction asynchrone, gérée par le runtime Tokio.
|
||||
// Sans ça, Rust ne saurait pas comment exécuter du code `async`.
|
||||
async fn main() {
|
||||
use axum::Router;
|
||||
use leptos::config::get_configuration;
|
||||
use leptos_axum::{generate_route_list, LeptosRoutes};
|
||||
use rust_ipam::{app::App, server::routes::not_found_handler};
|
||||
use tower_http::services::ServeDir;
|
||||
|
||||
// Initialise le système de logs structurés.
|
||||
// Les macros tracing::info!(), tracing::warn!(), tracing::error!()
|
||||
// n'affichent rien sans cet initialisateur.
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(
|
||||
// Lire le niveau de log depuis la variable d'environnement RUST_LOG,
|
||||
// ou utiliser "info" par défaut si elle n'est pas définie.
|
||||
// `unwrap_or_else` est une alternative idiomatique à `unwrap()` :
|
||||
// elle fournit une valeur de repli au lieu de paniquer.
|
||||
std::env::var("RUST_LOG").unwrap_or_else(|_| "info".to_string()),
|
||||
)
|
||||
.init();
|
||||
|
||||
tracing::info!("Démarrage du serveur Rust IPAM...");
|
||||
|
||||
// Charge la configuration Leptos.
|
||||
// Leptos peut lire un fichier `Leptos.toml` ou utiliser des valeurs par défaut.
|
||||
// On utilise `.expect()` car le serveur ne peut pas fonctionner sans configuration.
|
||||
// La chaîne passée à expect() est affichée si la valeur est Err ou None.
|
||||
// Note : get_configuration() est synchrone en Leptos 0.7 — pas de .await ici.
|
||||
let conf = get_configuration(None)
|
||||
.expect("Impossible de charger la configuration Leptos");
|
||||
let leptos_options = conf.leptos_options;
|
||||
let addr = leptos_options.site_addr;
|
||||
|
||||
// Analyse statiquement tous les composants `<Route>` dans `App`
|
||||
// pour construire la liste des URLs que Leptos doit gérer.
|
||||
let routes = generate_route_list(App);
|
||||
|
||||
// Construit le routeur Axum avec le pattern builder.
|
||||
// Chaque méthode retourne un nouveau Router modifié — c'est du chaînage fonctionnel.
|
||||
let app = Router::new()
|
||||
// Sert les fichiers statiques compilés par trunk (WASM, CSS, JS...).
|
||||
// `trunk build` les place dans `target/site/pkg/`.
|
||||
// Les navigateurs les demandent via des URLs comme `/pkg/rust-ipam.wasm`.
|
||||
.nest_service("/pkg", ServeDir::new("target/site/pkg"))
|
||||
// Branche toutes les routes Leptos dans Axum.
|
||||
// Pour chaque URL dans `routes`, Axum rend le composant App() en HTML.
|
||||
.leptos_routes(&leptos_options, routes, App)
|
||||
// Handler de repli : toute URL non reconnue retourne une 404.
|
||||
.fallback(not_found_handler)
|
||||
// Partage les options Leptos avec tous les handlers via le système d'état Axum.
|
||||
.with_state(leptos_options);
|
||||
|
||||
// Crée un listener TCP sur l'adresse configurée (par défaut 127.0.0.1:3000).
|
||||
let listener = tokio::net::TcpListener::bind(&addr)
|
||||
.await
|
||||
.expect(&format!("Impossible d'écouter sur l'adresse {}", addr));
|
||||
|
||||
tracing::info!("Serveur disponible sur http://{}", addr);
|
||||
|
||||
// Lance le serveur. Cette ligne bloque jusqu'à un Ctrl+C.
|
||||
axum::serve(listener, app)
|
||||
.await
|
||||
.expect("Erreur critique du serveur");
|
||||
}
|
||||
|
||||
// Ce bloc vide est nécessaire pour que le compilateur trouve un `fn main()`
|
||||
// quand on compile en mode WASM (où la feature "ssr" n'est pas activée).
|
||||
// En WASM, le vrai point d'entrée est la fonction `hydrate()` dans lib.rs.
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
fn main() {}
|
||||
|
||||
Reference in New Issue
Block a user