Web 框架的 SPA 功能集成
支持 Actix-web、Axum、Salvo 三大框架,通过统一的 spa! 宏将前端静态资源嵌入 Rust 二进制文件并提供 SPA 路由服务。
使用方法
添加依赖
anycms-spa = { version = "*", features = ["actix"] }
anycms-spa = { version = "*", features = ["axum"] }
anycms-spa = { version = "*", features = ["salvo"] }
rust-embed = "8.9.0"
paste = "1.0.15"
spa! 宏使用
宏需要用在 main.rs 或者 lib.rs 文件中
spa!(Spa, "assets");
spa!(Spa, "assets", "/", ["index.html"]);
spa!(Dashboard, "dashboard", "/dashboard", ["index.html"]);
示例代码
Actix-web 示例
use actix_web::{App, HttpResponse, HttpServer, Responder, get};
use anycms_spa::spa;
use tracing::info;
spa!(Spa, "assets", "/", ["index.html"]);
spa!(Dashboard, "dashboard", "/dashboard", ["index.html"]);
#[tokio::main]
async fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt::init();
info!("Hello, world!");
HttpServer::new(|| {
App::new()
.service(index)
.service(Dashboard::spa_service())
.service(Spa::spa_service())
})
.bind("127.0.0.1:8080")?
.run()
.await?;
Ok(())
}
#[get("/home")]
pub async fn index() -> impl Responder {
HttpResponse::Ok().body("Hello world!")
}
Axum 示例
use anycms_spa::spa;
use axum::{routing::get, Router};
spa!(Spa, "assets");
spa!(Dashboard, "dashboard", "/dashboard", ["index.html"]);
#[tokio::main]
async fn main() {
tracing_subscriber::fmt::init();
let app = Router::new()
.route("/home", get(root))
.merge(Dashboard::spa_router())
.merge(Spa::spa_router());
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
async fn root() -> &'static str {
"Hello, World!"
}
Salvo 示例
use anycms_spa::spa;
use salvo::prelude::*;
spa!(Spa, "assets");
spa!(Dashboard, "dashboard", "/dashboard", ["index.html"]);
#[handler]
async fn home(res: &mut Response) {
res.render(Text::Plain("Hello, World!"));
}
#[tokio::main]
async fn main() {
tracing_subscriber::fmt::init();
let router = Router::new()
.push(Router::with_path("/home").get(home))
.push(Dashboard::spa_router())
.push(Spa::spa_router());
let listener = TcpListener::new("0.0.0.0:3000").bind().await;
Server::new(listener).serve(router).await;
}
API 对比
| 框架 |
宏生成的方法 |
返回类型 |
| Actix-web |
Struct::spa_service() |
actix_web::Resource |
| Axum |
Struct::spa_router() |
axum::Router |
| Salvo |
Struct::spa_router() |
salvo::Router |
路由行为
- 静态资源(JS/CSS/图片等):直接返回,设置
Cache-Control: public, max-age=31536000
- HTML 页面:设置
Cache-Control: no-cache
- 未匹配路径:SPA fallback,返回
index.html,实现前端路由
- 路径遍历防护:自动拒绝包含
.. 的恶意路径
完整示例
查看 examples/ 目录获取可运行的完整项目。