Rust全栈Web开发框架Leptos与Actix集成库leptos_actix的使用:构建高性能响应式应用

// 使用leptos_actix集成库的完整示例

use actix_web::{web, App, HttpServer};
use leptos::*;
use leptos_actix::{generate_route_list, LeptosRoutes};

// 定义Leptos组件
#[component]
fn AppComponent(cx: Scope) -> impl IntoView {
    let (count, set_count) = create_signal(cx, 0);
    
    view! { cx,
        <main>
            <h1>"欢迎使用Leptos + Actix!"</h1>
            <button
                on:click=move |_| set_count.update(|n| *n += 1)
            >
                "点击计数: " {count}
            </button>
        </main>
    }
}

// 配置Leptos选项
#[actix_web::main]
async fn main() -> std::io::Result<()> {
    // 设置Leptos配置
    let conf = get_configuration(None).await.unwrap();
    let addr = conf.leptos_options.site_addr;
    
    // 生成路由列表
    let routes = generate_route_list(AppComponent);
    
    println!("服务器运行在: http://{}", &addr);
    
    HttpServer::new(move || {
        let leptos_options = &conf.leptos_options;
        let site_root = &leptos_options.site_root;
        
        App::new()
            // 提供Leptos路由
            .leptos_routes(
                leptos_options.to_owned(),
                routes.to_owned(),
                AppComponent,
            )
            // 提供静态文件服务
            .service(actix_files::Files::new("/", site_root))
    })
    .bind(&addr)?
    .run()
    .await
}

// Cargo.toml依赖配置示例
/*
[package]
name = "leptos-actix-demo"
version = "0.1.0"
edition = "2021"

[dependencies]
leptos = { version = "0.5", features = ["csr"] }
leptos_actix = "0.8.5"
actix-web = "4.4"
actix-files = "0.6"
serde = { version = "1.0", features = ["derive"] }

[build-dependencies]
leptos = { version = "0.5", features = ["csr"] }
*/

这个示例展示了如何使用leptos_actix集成库将Leptos前端框架与Actix-web后端框架结合使用。主要包含:

  1. Leptos组件定义:创建了一个简单的计数器组件
  2. Actix服务器配置:设置HTTP服务器并集成Leptos路由
  3. 静态文件服务:提供前端资源文件服务
  4. 依赖配置:展示了所需的Cargo.toml依赖项

要运行此示例,需要按照内容中提供的安装命令添加leptos_actix依赖,并配置相应的构建选项。

完整示例代码:

// 完整可运行的leptos_actix集成示例

use actix_web::{web, App, HttpServer};
use leptos::*;
use leptos_actix::{generate_route_list, LeptosRoutes};

// 定义Leptos根组件
#[component]
fn AppComponent(cx: Scope) -> impl IntoView {
    // 创建响应式信号用于计数器
    let (count, set_count) = create_signal(cx, 0);
    
    // 构建视图
    view! { cx,
        <main style="font-family: Arial, sans-serif; padding: 2rem;">
            <h1>"欢迎使用Leptos + Actix集成示例"</h1>
            <p>"这是一个完整的全栈Rust Web应用示例"</p>
            
            <div style="margin: 2rem 0;">
                <button
                    style="padding: 0.5rem 1rem; font-size: 1rem;"
                    on:click=move |_| set_count.update(|n| *n += 1)
                >
                    "点击计数: " {count}
                </button>
            </div>
            
            <div>
                <p>"当前计数: " <strong>{count}</strong></p>
            </div>
        </main>
    }
}

// 主函数 - Actix-web服务器入口点
#[actix_web::main]
async fn main() -> std::io::Result<()> {
    // 获取Leptos配置
    let conf = get_configuration(None).await.unwrap();
    let addr = conf.leptos_options.site_addr;
    
    // 生成应用路由列表
    let routes = generate_route_list(AppComponent);
    
    // 打印服务器启动信息
    println!("🚀 服务器启动成功!");
    println!("📡 访问地址: http://{}", &addr);
    println!("🔄 Leptos路由已配置");
    
    // 创建并配置HTTP服务器
    HttpServer::new(move || {
        let leptos_options = &conf.leptos_options;
        let site_root = &leptos_options.site_root;
        
        App::new()
            // 集成Leptos路由处理
            .leptos_routes(
                leptos_options.to_owned(),
                routes.to_owned(),
                AppComponent,
            )
            // 提供静态文件服务(CSS、JS等)
            .service(actix_files::Files::new("/", site_root))
            // 默认路由处理
            .default_service(web::route().to(leptos_actix::handle_server_fns))
    })
    .bind(&addr)?
    .run()
    .await
}

// 可选的错误处理页面组件
#[component]
fn ErrorPage(cx: Scope) -> impl IntoView {
    view! { cx,
        <div style="text-align: center; padding: 2rem;">
            <h1>"页面未找到"</h1>
            <p>"抱歉,您访问的页面不存在"</p>
        </div>
    }
}

对应的Cargo.toml配置文件:

[package]
name = "leptos-actix-demo"
version = "0.1.0"
edition = "2021"

[dependencies]
leptos = { version = "0.5", features = ["csr"] }
leptos_actix = "0.8.5"
actix-web = "4.4"
actix-files = "0.6"
serde = { version = "1.0", features = ["derive"] }

[build-dependencies]
leptos = { version = "0.5", features = ["csr"] }

构建和运行说明:

  1. 创建新的Rust项目:cargo new leptos-actix-demo
  2. 将上述代码复制到src/main.rs
  3. 将Cargo.toml配置复制到项目根目录
  4. 运行项目:cargo run
  5. 在浏览器中访问 http://localhost:3000

这个完整示例包含了基本的Leptos组件、Actix-web服务器配置、静态文件服务和错误处理,可以直接运行使用。


1 回复

Leptos与Actix集成库leptos_actix使用指南

概述

leptos_actix是一个将Leptos前端框架与Actix-web后端服务器无缝集成的库,让开发者能够构建高性能的响应式Web应用。它提供了服务端渲染(SSR)、API路由处理和前端组件渲染的统一解决方案。

核心特性

  • 服务端渲染(SSR)支持
  • 客户端hydration
  • 统一的API路由处理
  • 热重载开发体验
  • 类型安全的端到端通信

安装配置

在Cargo.toml中添加依赖:

[dependencies]
leptos = "0.5"
leptos_actix = "0.2"
actix-web = "4.4"

基本使用示例

1. 定义Leptos组件

use leptos::*;

#[component]
pub fn App(cx: Scope) -> impl IntoView {
    let (count, set_count) = create_signal(cx, 0);
    
    view! { cx,
        <main>
            <h1>"Leptos + Actix计数器"</h1>
            <button on:click=move |_| set_count.update(|n| *n += 1)>
                "点击次数: " {count}
            </button>
        </main>
    }
}

2. 配置Actix服务器

use actix_web::*;
use leptos_actix::{generate_route_list, LeptosRoutes};
use leptos::*;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let conf = get_configuration(None).unwrap();
    let addr = conf.leptos_options.site_addr;
    let routes = generate_route_list(|cx| view! { cx, <App/> });

    HttpServer::new(move || {
        let leptos_options = &conf.leptos_options;
        let site_root = &leptos_options.site_root;

        App::new()
            .route("/api/{tail:.*}", leptos_actix::handle_server_fns())
            .leptos_routes(leptos_options.to_owned(), routes.to_owned(), |cx| {
                view! { cx, <App/> }
            })
            .service(fs::Files::new("/", site_root))
    })
    .bind(&addr)?
    .run()
    .await
}

3. 创建服务器函数

#[server(GetUserData, "/api")]
pub async fn get_user_data(user_id: i32) -> Result<String, ServerFnError> {
    // 模拟数据库查询
    Ok(format!("用户{}的数据", user_id))
}

#[component]
pub fn UserProfile(cx: Scope, user_id: i32) -> impl IntoView {
    let user_data = create_resource(
        cx,
        move || user_id,
        |id| async move { get_user_data(id).await }
    );

    view! { cx,
        <div>
            <h2>"用户信息"</h2>
            <Suspense fallback=move || view! { cx, <p>"加载中..."</p> }>
                {move || user_data.read().map(|data| 
                    view! { cx, <p>{data.unwrap_or_else(|_| "加载失败".to_string())}</p> }
                )}
            </Suspense>
        </div>
    }
}

完整示例demo

基于上述示例,这里提供一个完整的leptos_actix集成项目示例:

Cargo.toml

[package]
name = "leptos-actix-demo"
version = "0.1.0"
edition = "2021"

[dependencies]
leptos = { version = "0.5", features = ["serde", "ssr"] }
leptos_actix = "0.2"
actix-web = "4.4"
serde = { version = "1.0", features = ["derive"] }

src/main.rs

use actix_web::*;
use leptos::*;
use leptos_actix::{generate_route_list, LeptosRoutes};

// 导入自定义组件
use leptos_actix_demo::App;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    // 获取Leptos配置
    let conf = get_configuration(None).unwrap();
    let addr = conf.leptos_options.site_addr;
    
    // 生成路由列表
    let routes = generate_route_list(|cx| view! { cx, <App/> });

    println!("服务器运行在: http://{}", &addr);

    HttpServer::new(move || {
        let leptos_options = &conf.leptos_options;
        let site_root = &leptos_options.site_root;

        App::new()
            // 注册API路由处理
            .route("/api/{tail:.*}", leptos_actix::handle_server_fns())
            // 注册Leptos路由
            .leptos_routes(
                leptos_options.to_owned(),
                routes.to_owned(),
                |cx| view! { cx, <App/> },
            )
            // 静态文件服务
            .service(fs::Files::new("/", site_root))
    })
    .bind(&addr)?
    .run()
    .await
}

src/lib.rs

use leptos::*;
use serde::{Deserialize, Serialize};

// 主应用组件
#[component]
pub fn App(cx: Scope) -> impl IntoView {
    let (count, set_count) = create_signal(cx, 0);
    
    view! { cx,
        <main style="font-family: Arial, sans-serif; padding: 20px;">
            <h1>"Leptos + Actix 全栈示例"</h1>
            <div>
                <button 
                    on:click=move |_| set_count.update(|n| *n += 1)
                    style="padding: 10px 20px; font-size: 16px;"
                >
                    "点击次数: " {count}
                </button>
            </div>
            <hr/>
            <UserProfile user_id=1/>
        </main>
    }
}

// 服务器函数 - 获取用户数据
#[server(GetUserData, "/api")]
pub async fn get_user_data(user_id: i32) -> Result<String, ServerFnError> {
    // 模拟数据库查询或API调用
    tokio::time::sleep(std::time::Duration::from_secs(1)).await; // 模拟延迟
    Ok(format!("用户ID {} 的详细信息: 姓名: 张三, 年龄: 25, 职业: 开发者", user_id))
}

// 用户资料组件
#[component]
pub fn UserProfile(cx: Scope, user_id: i32) -> impl IntoView {
    let user_data = create_resource(
        cx,
        move || user_id,
        |id| async move { get_user_data(id).await }
    );

    view! { cx,
        <div style="margin-top: 20px;">
            <h2>"用户信息"</h2>
            <Suspense fallback=move || view! { cx, 
                <p style="color: #666;">"加载用户数据中..."</p> 
            }>
                {move || user_data.read().map(|data| 
                    match data {
                        Ok(data) => view! { cx, 
                            <div style="background: #f5f5f5; padding: 15px; border-radius: 5px;">
                                <p>{data}</p>
                            </div>
                        },
                        Err(_) => view! { cx, 
                            <p style="color: red;">"加载用户数据失败"</p> 
                        }
                    }
                )}
            </Suspense>
        </div>
    }
}

项目结构建议

src/
├── main.rs          # Actix服务器入口
├── lib.rs           # Leptos组件和共享代码
├── app/
│   ├── mod.rs
│   └── components/  # 可复用组件
└── api/
    ├── mod.rs
    └── handlers/    # API处理函数

开发命令

# 开发模式(带热重载)
cargo leptos watch

# 生产构建
cargo leptos build --release

# 运行生产服务器
cargo run --release

注意事项

  1. 确保在Cargo.toml中正确配置leptos特性标志
  2. 服务器函数必须标记为async并使用#[server]
  3. 正确处理错误类型,使用ServerFnError作为返回类型
  4. 注意静态资源文件的路径配置

这个集成方案提供了完整的全栈开发体验,结合了Leptos的响应式前端和Actix的高性能后端优势。

回到顶部