Rust全栈开发框架Dioxus-Fullstack的使用:构建高性能跨平台Web应用与桌面程序
Rust全栈开发框架Dioxus-Fullstack的使用:构建高性能跨平台Web应用与桌面程序
Dioxus Fullstack
Dioxus框架的全栈工具。
特性
- 与Axum服务器框架集成,提供服务和渲染Dioxus应用的实用工具
- 服务器功能允许您从客户端调用服务器上的代码,就像调用普通函数一样
- 使用dioxus-hot-reload实现即时RSX热重载
- 从服务器向客户端传递根属性
示例
不到30行代码实现全栈Dioxus
#![allow(non_snake_case)]
use dioxus::prelude::*;
fn main() {
dioxus::launch(App);
}
#[component]
fn App() -> Element {
let mut meaning = use_signal(|| None);
rsx! {
h1 { "Meaning of life: {meaning:?}" }
button {
onclick: move |_| async move {
if let Ok(data) = get_meaning("life the universe and everything".into()).await {
meaning.set(data);
}
},
"Run a server function"
}
}
}
#[server]
async fn get_meaning(of: String) -> Result<Option<u32>, ServerFnError> {
Ok(of.contains("life").then(|| 42))
}
Axum集成
如果您已有Axum路由器或需要更多服务器控制,可以使用DioxusRouterExt特性与现有Axum路由器集成。
首先,确保您的axum依赖是可选的,并通过服务器特性标志启用:
[dependencies]
dioxus = { version = "*", features = ["fullstack"] }
axum = { version = "0.7.0", optional = true }
tokio = { version = "1.0", features = ["full"], optional = true }
dioxus-cli-config = { version = "*", optional = true }
[features]
server = ["dioxus/server", "dep:axum", "dep:tokio", "dioxus-cli-config"]
web = ["dioxus/web"]
然后我们可以设置带有axum服务器的dioxus:
#![allow(non_snake_case)]
use dioxus::prelude::*;
// 服务器的入口点
#[cfg(feature = "server")]
#[tokio::main]
async fn main() {
// 获取服务器应运行的地址
let address = dioxus::cli_config::fullstack_address_or_localhost();
// 设置axum路由器
let router = axum::Router::new()
// 使用`serve_dioxus_application`方法将dioxus应用程序添加到路由器
.serve_dioxus_application(ServeConfigBuilder::default(), App);
// 最后启动服务器
let router = router.into_make_service();
let listener = tokio::net::TcpListener::bind(address).await.unwrap();
axum::serve(listener, router).await.unwrap();
}
// 对于其他平台,只需启动应用程序
#[cfg(not(feature = "server"))]
fn main() {
dioxus::launch(App);
}
#[component]
fn App() -> Element {
let mut meaning = use_signal(|| None);
rsx! {
h1 { "Meaning of life: {meaning:?}" }
button {
onclick: move |_| async move {
if let Ok(data) = get_meaning("life the universe and everything"].into()).await {
meaning.set(data);
}
},
"Run a server function"
}
}
}
#[server]
async fn get_meaning(of: String) -> Result<Option<u32>, ServerFnError> {
Ok(of.contains("life").then(|| 42))
}
完整示例Demo
以下是一个完整的Dioxus-Fullstack示例,包含客户端和服务器端代码:
// Cargo.toml
[package]
name = "dioxus-fullstack-demo"
version = "0.1.0"
edition = "2021"
[dependencies]
dioxus = { version = "0.6", features = ["fullstack"] }
axum = { version = "0.7", optional = true }
tokio = { version = "1.0", features = ["full"], optional = true }
dioxus-cli-config = { version = "0.6", optional = true }
serde = { version = "1.0", features = ["derive"] }
[features]
server = ["dioxus/server", "dep:axum", "dep:tokio", "dioxus-cli-config"]
web = ["dioxus/web"]
// src/main.rs
#![allow(non_snake_case)]
use dioxus::prelude::*;
// 服务器入口点
#[cfg(feature = "server")]
#[tokio::main]
async fn main() {
use axum::Router;
use dioxus_fullstack::prelude::*;
let addr = dioxus::cli_config::fullstack_address_or_localhost();
println!("Server running on: {}", addr);
let router = Router::new()
.serve_dioxus_application(ServeConfigBuilder::default(), App);
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
axum::serve(listener, router.into_make_service())
.await
.unwrap();
}
// 客户端入口点
#[cfg(not(feature = "server"))]
fn main() {
dioxus::launch(App);
}
#[component]
fn App() -> Element {
let mut count = use_signal(|| 0);
let mut server_data = use_signal(|| None);
rsx! {
h1 { "Dioxus Fullstack Demo" }
div {
h2 { "Client State: {count}" }
button {
onclick: move |_| count += 1,
"Increment"
}
button {
onclick: move |_| count -= 1,
"Decrement"
}
}
div {
h2 { "Server Interaction" }
button {
onclick: move |_| async move {
if let Ok(data) = fetch_data(count()).await {
server_data.set(Some(data));
}
},
"Fetch from Server"
}
if let Some(data) = server_data() {
p { "Server response: {data}" }
}
}
}
}
#[server]
async fn fetch_data(client_count: i32) -> Result<String, ServerFnError> {
// 模拟一些服务器处理
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
// 返回处理后的数据
Ok(format!("Server processed your count: {}", client_count * 2))
}
开始使用
要开始使用全栈Dioxus,请查看入门指南或完整堆栈示例。
贡献
- 在问题跟踪器上报告问题
- 加入discord并提问
许可证
本项目根据MIT许可证授权。
1 回复
Rust全栈开发框架Dioxus-Fullstack的使用:构建高性能跨平台Web应用与桌面程序
Dioxus-Fullstack是一个基于Rust的全栈开发框架,允许开发者使用同一套代码构建Web应用和桌面程序。它结合了前端框架Dioxus和后端能力,提供了完整的全栈开发体验。
核心特性
- 跨平台支持:一套代码可编译为Web应用、桌面应用(Windows/macOS/Linux)和移动端应用
- 高性能:得益于Rust的零成本抽象和高效内存管理
- 响应式UI:类似React的声明式组件模型
- 全栈能力:内置前后端通信机制
- 热重载:开发时快速迭代
安装与设置
首先确保已安装Rust工具链,然后添加Dioxus依赖:
# Cargo.toml
[dependencies]
dioxus = { version = "0.4", features = ["fullstack"] }
dioxus-fullstack = "0.4"
基础使用示例
1. 创建基本应用
use dioxus::prelude::*;
fn App(cx: Scope) -> Element {
cx.render(rsx! {
div {
h1 { "欢迎使用Dioxus-Fullstack!" }
p { "这是一个全栈Rust应用" }
Counter {}
}
})
}
#[component]
fn Counter(cx: Scope) -> Element {
let mut count = use_state(cx, || 0);
cx.render(rsx! {
div {
button { onclick: move |_| count += 1, "增加" }
button { onclick: move |_| count -= 1, "减少" }
p { "当前计数: {count}" }
}
})
}
2. 全栈通信示例
前端代码 (client.rs):
use dioxus::prelude::*;
use dioxus_fullstack::prelude::*;
fn App(cx: Scope) -> Element {
let response = use_future(cx, (), |_| async move {
get_server_data().await
});
cx.render(rsx! {
div {
h1 { "服务器数据" }
match response.value() {
Some(Ok(data)) => rsx! { p { "服务器说: {data}" } },
Some(Err(err)) => rsx! { p { "错误: {err}" } },
None => rsx! { p { "加载中..." } },
}
}
})
}
#[server]
async fn get_server_data() -> Result<String, ServerFnError> {
Ok("你好,来自服务器的消息!".to_string())
}
后端代码 (server.rs):
use dioxus_fullstack::prelude::*;
#[tokio::main]
async fn main() {
let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 8080));
axum::Server::bind(&addr)
.serve(
app()
.into_make_service()
)
.await
.unwrap();
}
fn app() -> Router {
Router::new()
.serve_dioxus_application("", ServeConfig::builder().build())
.register_server_fns()
}
构建与运行
开发模式
# 运行全栈开发服务器
dx serve --hot-reload
生产构建
# 构建Web应用
dx build --release --target web
# 构建桌面应用
dx build --release --target desktop
桌面应用打包
Dioxus-Fullstack支持使用Tauri打包桌面应用:
# Cargo.toml
[dependencies]
tauri = { version = "1.0", features = [] }
然后运行:
cargo tauri build
高级功能
1. 状态管理
use dioxus::prelude::*;
use dioxus_fullstack::prelude::*;
#[derive(Clone, Routable)]
enum Route {
#[route("/")]
Home {},
#[route("/about")]
About {},
}
fn App(cx: Scope) -> Element {
cx.render(rsx! {
Router::<Route> {}
})
}
#[component]
fn Home(cx: Scope) -> Element {
cx.render(rsx! { h1 { "首页" } })
}
#[component]
fn About(cx: Scope) -