8 releases (5 breaking)
0.6.0 | Dec 5, 2024 |
---|---|
0.5.1 | Dec 3, 2024 |
0.5.0 | Jun 26, 2024 |
0.4.0 | Jun 12, 2024 |
0.1.1 | Nov 11, 2023 |
#1154 in Network programming
313 downloads per month
42KB
832 lines
axum-inertia
Implementation of the inertia.js protocol for axum.
Provides an Inertia
axum extractor to render responses like so:
async fn get_posts(i: Inertia) -> impl IntoResponse {
i.render("Posts/Index", json!({ "posts": vec!["post one", "post two"] }))
}
See crate documentation for more information.
Making a new release
- Spin off a
bump-vX.X.X
branch - Update the
CHANGELOG
; start a new[Unreleased]
section - Bump the version number in
Cargo.toml
- Run
cargo release --execute
(requires cargo-release) - Merge PR if all goes well
lib.rs
:
An implementation of the inertia.js protocol for axum.
The basic idea is that any axum handler that accepts the Inertia
struct as a function parameter is an inertia endpoint. For
instance:
use axum_inertia::Inertia;
use axum::{Json, response::IntoResponse};
use serde_json::json;
async fn my_handler_fn(i: Inertia) -> impl IntoResponse {
i.render("Pages/MyPageComponent", json!({"myPageProps": "true"}))
}
This does the following:
-
If the incoming request is the initial page load (i.e., does not have the
X-Inertia
header set totrue
), the render method responds with an html page, which is configurable when setting up the initial Inertia state (see Getting started below). -
Otherwise, the handler responses with the standard inertia "Page" object json, with the included component and page props passed to render.
-
If the request has a mismatching asset version (again, this is configurable), the handler responds with a
409 Conflict
to tell the client to reload the page. The function body of the handler is not executed in this case.
Getting started
First, you'll need to provide your axum routes with [InertiaConfig] state. This state boils down to two things: an optional string representing the asset version and a function that takes serialized props and returns an HTML string for the initial page load.
The [vite] module provides a convenient way to set up this state with axum::Router::with_state. For instance, the following code sets up a standard development server:
use axum_inertia::{vite, Inertia};
use axum::{Router, routing::get, response::IntoResponse};
// Configuration for Inertia when using `vite dev`:
let inertia = vite::Development::default()
.port(5173)
.main("src/main.ts")
.lang("en")
.title("My inertia app")
.into_config();
let app: Router = Router::new()
.route("/", get(get_root))
.with_state(inertia);
The [Inertia] struct is then available as an axum Extractor and can be used in handlers like so:
use axum_inertia::Inertia;
use serde_json::json;
async fn get_root(i: Inertia) -> impl IntoResponse {
i.render("Pages/Home", json!({ "posts": vec!["post one", "post two"] }))
}
The Inertia::render method takes care of building a response conforming to the inertia.js protocol. It takes two parameters: the name of the component to render, and the page props (serializable to json).
Using the extractor in a handler requires that you use axum::Router::with_state to initialize Inertia in your routes. In fact, it won't compile if you don't!
Using InertiaConfig as substate
It's likely you'll want other pieces of state beyond [InertiaConfig]. You'll just need to implement axum::extract::FromRef for your state type for [InertiaConfig]. For instance:
use axum::response::IntoResponse;
use axum::{extract::FromRef, routing::get, Router};
use axum_inertia::{vite, Inertia, InertiaConfig};
#[derive(Clone)]
struct AppState {
inertia: InertiaConfig,
name: String,
}
impl FromRef<AppState> for InertiaConfig {
fn from_ref(app_state: &AppState) -> InertiaConfig {
app_state.inertia.clone()
}
}
let inertia = vite::Development::default()
.port(5173)
.main("src/main.ts")
.lang("en")
.title("My inertia app")
.into_config();
let app_state = AppState {
inertia,
name: "foo".to_string(),
};
let app: Router = Router::new()
.route("/", get(get_root))
.with_state(app_state);
Configuring development and production
See the [vite] module for more information.
Dependencies
~6–13MB
~160K SLoC