#axum #inertia #js #response #render #protocols #page

axum-inertia

为 Axum 实现的 Inertia.js 协议

6 个版本 (破坏性更新)

0.5.0 2024年6月26日
0.4.0 2024年6月12日
0.3.0 2024年2月13日
0.2.0 2023年11月28日
0.1.1 2023年11月11日

#908 in 网络编程

Download history 140/week @ 2024-06-12 1/week @ 2024-06-19 183/week @ 2024-06-26 4/week @ 2024-07-03

每月329次下载

MIT/Apache

40KB
800

Crates.io Documentation

axum-inertia

为 axum 实现的 inertia.js 协议。

提供了一个 Inertia axum 提取器,以渲染响应,如下所示

async fn get_posts(i: Inertia) -> impl IntoResponse {
    i.render("Posts/Index", json!({ "posts": vec!["post one", "post two"] }))
}

有关更多信息,请参阅 crate 文档

发布新版本

  1. bump-.X.X 分支分叉
  2. 更新 CHANGELOG;开始一个新的 [Unreleased] 部分
  3. Cargo.toml 中更新版本号
  4. 运行 cargo release --execute
  5. 如果一切顺利,合并 PR

lib.rs:

inertia.js 协议实现 axum

基本思路是,任何接受 Inertia 结构体作为函数参数的 axum 处理器都是一个惯性端点。例如

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"}))
}

这会执行以下操作

  • 如果传入的请求是初始页面加载(即没有将 X-Inertia 标头设置为 true),则 render 方法会响应一个 HTML 页面,该页面在设置初始 Inertia 状态时可配置(见下文 入门)。

  • 否则,处理器响应标准惯性 "Page" 对象 JSON,其中包含传递给 render 的组件和页面属性。

  • 如果请求有不匹配的资产版本(这同样是可以配置的),处理程序将响应一个 409 冲突,告诉客户端重新加载页面。在这种情况下,处理程序的主体函数不会执行。

入门指南

首先,您需要为 axum 路由提供 [InertiaConfig] 状态。这个状态归结为两件事:一个表示 资产版本 的可选字符串,以及一个接收序列化属性并返回初始页面加载的 HTML 字符串的函数。

[vite] 模块提供了一个方便的方法,使用 axum::Router::with_state 来设置此状态。例如,以下代码设置了一个标准的开发服务器

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);

然后,[Inertia] 结构体可以作为 axum 的 提取器 使用,并在处理程序中如下所示使用

use axum::response::IntoResponse;
use serde_json::json;

async fn get_root(i: Inertia) -> impl IntoResponse {
    i.render("Pages/Home", json!({ "posts": vec!["post one", "post two"] }))
}

Inertia::render 方法负责构建符合 inertia.js 协议 的响应。它接受两个参数:要渲染的组件名称和页面属性(可序列化为 json)。

在处理程序中使用提取器需要您使用 axum::Router::with_state 在路由中初始化 Inertia。[InertiaConfig] 作为子状态使用

使用 InertiaConfig 作为子状态

您可能还想要其他一些状态,而不仅仅是 [InertiaConfig]。您只需为您的状态类型实现 [InertiaConfig] 的 axum::extract::FromRef。例如

use axum_inertia::{vite, Inertia, InertiaConfig};
use axum::{Router, routing::get, extract::FromRef};

#[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);

配置开发和生产环境

有关更多信息,请参阅 [vite] 模块。

依赖项

~6.5–8.5MB
~158K SLoC