在本文中,我们将探索Rust生态系统中用于前端和后端开发的各种web框架。
如何选择最好的Rust web框架
无论你的项目需要什么,web框架都可以提供开发团队需要的web服务、web资源和web api。在为项目选择合适的web框架时,开发团队应该考虑以下因素的相对重要性。
安全性
Rust的内存安全保证了安全性,这是通过它的所有权模型实现的。然而,并不是所有的Rust web框架都能处理安全特性,比如跨站脚本(XSS)和跨站请求伪造(CSRF)。因此,你应该注意如何在框架中处理安全性。
灵活性
框架的灵活性通常归结为你需要多少可控性,以及你希望在多大程度上依赖抽象和约定。根据你的经验来考虑框架的灵活性以及它如何使你的项目受益。
项目大小
较小的项目可能倾向于使用更简单、更高级的抽象,而较大的项目则需要可伸缩性和高效的并发性。
版本及时更新
与框架的开发保持同步是很重要的——你不会想要使用上一次更新是五年前的框架,因为它可能会影响安全性和与最新Rust特性的兼容性。
文档
清晰、结构良好的文档可以显著加快开发速度,尤其是在新开发人员入职时。
社区支持
社区的规模和参与度决定了在项目过程中出现问题时找到资源、库和帮助的难易程度——“bug是工作的一部分”。
前端Web框架和WebAssembly
WebAssembly(Wasm)是一种可以在现代web浏览器中运行的底层语言编码,它支持C/C++, c#, Go和Rust,并可以编译成目标机器的字节码,因此它可以以接近本机的性能运行在web上。Wasm与JavaScript一起运行,可以发布到npm和其他包中。Rust使用一个名为wasm-pack的工具来组装和打包针对WASM的crate。
Yew
Yew是最流行的Rust框架之一(它目前在GitHub上有30.5万颗星),用于构建现代web应用程序。受React的启发,它利用了基于组件的体系结构,并提供了对状态管理、异步等的支持。
下面是一个使用Yew的Hello World应用的简单示例:
图片
可以通过运行以下命令快速探索它是如何工作的:
cargo install generate
cargo install trunk
cargo generate --git https://github.com/yewstack/yew-trunk-minimal-template
trunk serve --open
上面的代码片段将生成一个样板代码,可以用它作为Yew应用程序的起始模板。安装Trunk的原因是因为Yew使用Trunk捆绑器来为web提供HTML。
Perseus
Perseus是一个Rust框架,用于构建响应式web应用程序。它支持类似于Next.js的功能,但它是为Rust生态系统设计的。
Perseus的响应式系统由Sycamore响应式库提供支持,并具有对服务器端渲染(SSR)和静态站点生成(SSG)的原生支持。它目前有超过2.8k的GitHub颗星。
下面是一个如何用Perseus编写一个简单的Hello World应用程序的例子:
use perseus::prelude::*;
use sycamore::prelude::*;
#[perseus::main(perseus_axum::dflt_server)]
pub fn main() -> PerseusApp {
PerseusApp::new()
.template(
Template::build("index")
.view(|cx| {
view! { cx,
p { "Hello World!" }
}
})
.build()
)
}
要开始使用Perseus,运行下面的命令创建一个示例应用程序并启动服务器:
cargo install perseus-cli
perseus new my-app
cd my-app/
perseus serve -w
Sauron
Sauron是一个受Elm Architecture启发的微型前端框架。它支持事件、状态管理、客户端和服务器端web开发。一个最简单的方法来试验它是如何工作的是通过使用html2sauron将HTML转换为Sauron源代码,如下所示:
图片
Sauron在GitHub上有超过2k颗星,对于一个新框架来说,这真是令人印象深刻,这表明人们对该框架的兴趣正在增长。
Dioxus
Dioxus是一个Rust UI库,可以让你构建响应式跨平台UI组件——它支持web、移动和桌面应用程序开发。它借鉴了React的一些特性(包括钩子),并使用了自己的虚拟DOM——可以把它看作是React与Rust的安全性和速度的混合体。
这是Dioxus应用中组件的样子:
fn app(cx: Scope) -> Element {
let result: &mut u32 = cx.use_hook(|| 0);
cx.render(rsx!(
div { "Hello World" }
))
}
Dioxus拥有强大的社区支持之一,在GitHub上拥有超过20k颗星。
Iced
Iced是一个跨平台开发GUI库,它的架构也受到Elm架构的启发,并提供对响应式编程、类型安全和速度的内置支持。
Iced使用以下结构来编写代码:
- 状态:应用程序的状态
- 消息:你关心的用户交互或有意义的事件
- 视图逻辑:一种将状态显示为在用户交互时产生消息的方法
- 更新逻辑:一种对消息作出反应并更新状态的方法
这是一种将用户界面划分为不同概念的好方法,这些概念很容易推理。Iced社区也在迅速发展,GitHub上有超过2.4万颗星星。
Tauri
Tauri是一个基于rust的库,通过利用HTML、CSS和JavaScript等web技术为UI构建轻量级桌面应用程序。你可以使用任何可以编译成HTML、CSS和JavaScript的前端框架。
与依赖于Chromium和Node.js的Electron(一个JavaScript桌面应用开发框架)不同,Tauri使用的是系统的原生web视图。这使得的二进制文件更小和使用更有效的资源。
可以使用Tauri框架开发一个从前端到后端逻辑的全栈桌面应用程序。Tauri也拥有强大的社区支持,拥有超过81k个GitHub颗星。
后端Web框架
后端开发是web开发中关注服务器端的一个方面,典型的后端框架包括数据库管理、会话处理、模板、ORM和数据库迁移等功能,用于构建和维护可靠的web应用程序。
Rocket
Rocket是一个流行的Rust异步web框架,它简化了开发。它抽象了web开发的许多潜在复杂性,因此你可以专注于使用用户友好的API构建主要业务逻辑,而不会影响安全性和速度。
作为最早的Rust框架之一,它在GitHub上拥有超过24k颗星。
下面是一个简单的Rocket服务器示例,它接受两个查询参数并返回一个Happy Birthday消息:
#[macro_use] extern crate rocket;
#[get("//")]
fn birthday(name: &str, age: u8) -> String {
format!("Yayyy, {}, you are {} years old! Happy Birthday to you.", name, age)
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/birthday-message", routes![hello])
}
Actix Web
Actix Web是一个基于参与者模型的后端Web框架,可以构建大规模复杂的Web应用程序。虽然它很复杂,但它公开了底层实现以支持进一步的定制。
下面是一个简单的Happy Birthday API的例子,使用Actix Web来了解它是什么样子的:
use actix_web::{get, web, App, HttpServer, Responder};
#[get("/birthday-message/{name}/{age}")]
async fn birthday(name: web::Path<(String, u8)>) -> impl Responder {
format!(
"Hello, {}, you are {} years old! Happy Birthday!",
name.0, name.1
)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().service(birthday))
.bind("127.0.0.1:8080")?
.run()
.await
}
它有一个庞大的开发者社区,在GitHub上拥有超过21k颗星。
Axum
Axum是一个现代的、异步优先的web框架,建立在流行的Tokio生态系统之上,旨在构建可扩展和可维护的web应用程序。
Axum是一个非常健壮的web框架,但它并没有暴露太多底层实现以避免复杂性,因为它试图对社区中的新开发人员更友好,所以与Actix相比,你不会看到很多可怕的泛型,因为它抽象了其中的一些。它功能强大,支持许多现代web api,如HTTP/2、WebSockets等。
与Actix Web相比,Axum让初学者更容易构建中间件,这是我认为Axum最好的特性之一。
下面是一个简单的Happy Birthday API的例子:
use axum::{extract::Path, routing::get, Router};
async fn birthday(Path((name, age)): Path<(String, u8)>) -> String {
format!(
"Yayyy, {}, you are {} years old! Happy Birthday to you.",
name, age
)
}
#[tokio::main]
async fn main() {
let app = Router::new().route("/birthday/:name/:age", get(birthday));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
Axum的社区规模很大,而且还在不断增长,在GitHub上拥有超过18.3k颗星。
Warp
Warp的设计是快速、轻量级和可组合的,开始使用它并开始构建高性能api是很容易的。
为了进一步说明使用Warp是多么容易,这里有一个简单的API,模仿我们一直在使用的相同的Happy Birthday示例。它现在看起来短了很多,但仍然很容易理解:
use warp::Filter;
#[tokio::main]
async fn main() {
let birthday = warp::path!("birthday" / String / u8)
.map(|name, age| {
format!("Yayyy, {}, you are {} years old! Happy Birthday to you.", name, age)
});
warp::serve(birthday)
.run(([127, 0, 0, 1], 3030))
.await;
}
Warp在GitHub上有超过9.5k颗星,它的开发者社区还在继续增长!
Tide
Tide是一个小型框架,类似于Express.js (Node.js)、Sinatra (Ruby)和Flask (Python),用于快速开发,异步构建web应用程序。它拥有在大多数成熟的web框架中可以找到的大部分功能,包括路由、认证、套接字、日志、模板引擎、中间件、测试和其他实用程序。
下面是一个简单的Happy Birthday应用程序:
use tide::Request;
async fn birthday(_req: Request<()>) -> tide::Result {
Ok("Happy Birthday!
".into())
}
#[async_std::main]
async fn main() -> tide::Result<()> {
let mut app = tide::new();
app.at("/birthday").get(birthday);
app.listen("127.0.0.1:8080").await?;
Ok(())
}
Tide使用async-std,这是为了异步实现的速度和安全性而构建的,它在GitHub上也有大约5k颗星。
比较最流行的Rust web后端框架
Actix、Rocket、Axum和Warp都是流行的Rust web框架,每个框架都有自己独特的功能和优势。下面让我们仔细看看它们的共同点:
非阻塞IO
Actix、Rocket、Axum和warp都使用Rust的async/await语法为web应用程序提供非阻塞I/O操作。这允许更好的性能和可伸缩性,因为框架可以同时处理多个请求而不会阻塞或减慢速度。
中间件
中间件是web框架中的一个常见特性,它允许开发人员在请求-响应周期中添加功能,例如日志记录、身份验证和错误处理。所有最流行的Rust web框架——Actix、Rocket、Tide和warp都支持中间件。
WebSocket
它们都支持WebSocket,但是使用WebSocket的具体语法和特性可能因框架而异,因此框架的选择将取决于项目的具体需求。
高并发性
Actix和Axum可能更适合需要高并发性和高性能的应用程序,而Rocket和warp可能更适合优先考虑易用性和灵活性的应用程序。