探索頂級(jí)Rust Web框架,你學(xué)到了什么?
Web框架使開(kāi)發(fā)人員更容易進(jìn)行Web開(kāi)發(fā)和構(gòu)建桌面應(yīng)用程序,通過(guò)標(biāo)準(zhǔn)化構(gòu)建過(guò)程和自動(dòng)化常見(jiàn)的活動(dòng)和任務(wù),web框架可以節(jié)省開(kāi)發(fā)人員的時(shí)間,甚至可以促進(jìn)代碼的重用以提高效率。
在本文中,我們將探索Rust生態(tài)系統(tǒng)中用于前端和后端開(kāi)發(fā)的各種web框架。
如何選擇最好的Rust web框架
無(wú)論你的項(xiàng)目需要什么,web框架都可以提供開(kāi)發(fā)團(tuán)隊(duì)需要的web服務(wù)、web資源和web api。在為項(xiàng)目選擇合適的web框架時(shí),開(kāi)發(fā)團(tuán)隊(duì)?wèi)?yīng)該考慮以下因素的相對(duì)重要性。
安全性
Rust的內(nèi)存安全保證了安全性,這是通過(guò)它的所有權(quán)模型實(shí)現(xiàn)的。然而,并不是所有的Rust web框架都能處理安全特性,比如跨站腳本(XSS)和跨站請(qǐng)求偽造(CSRF)。因此,你應(yīng)該注意如何在框架中處理安全性。
靈活性
框架的靈活性通常歸結(jié)為你需要多少可控性,以及你希望在多大程度上依賴(lài)抽象和約定。根據(jù)你的經(jīng)驗(yàn)來(lái)考慮框架的靈活性以及它如何使你的項(xiàng)目受益。
項(xiàng)目大小
較小的項(xiàng)目可能傾向于使用更簡(jiǎn)單、更高級(jí)的抽象,而較大的項(xiàng)目則需要可伸縮性和高效的并發(fā)性。
版本及時(shí)更新
與框架的開(kāi)發(fā)保持同步是很重要的——你不會(huì)想要使用上一次更新是五年前的框架,因?yàn)樗赡軙?huì)影響安全性和與最新Rust特性的兼容性。
文檔
清晰、結(jié)構(gòu)良好的文檔可以顯著加快開(kāi)發(fā)速度,尤其是在新開(kāi)發(fā)人員入職時(shí)。
社區(qū)支持
社區(qū)的規(guī)模和參與度決定了在項(xiàng)目過(guò)程中出現(xiàn)問(wèn)題時(shí)找到資源、庫(kù)和幫助的難易程度——“bug是工作的一部分”。
前端Web框架和WebAssembly
WebAssembly(Wasm)是一種可以在現(xiàn)代web瀏覽器中運(yùn)行的底層語(yǔ)言編碼,它支持C/C++, c#, Go和Rust,并可以編譯成目標(biāo)機(jī)器的字節(jié)碼,因此它可以以接近本機(jī)的性能運(yùn)行在web上。Wasm與JavaScript一起運(yùn)行,可以發(fā)布到npm和其他包中。Rust使用一個(gè)名為wasm-pack的工具來(lái)組裝和打包針對(duì)WASM的crate。
Yew
Yew是最流行的Rust框架之一(它目前在GitHub上有30.5萬(wàn)顆星),用于構(gòu)建現(xiàn)代web應(yīng)用程序。受React的啟發(fā),它利用了基于組件的體系結(jié)構(gòu),并提供了對(duì)狀態(tài)管理、異步等的支持。
下面是一個(gè)使用Yew的Hello World應(yīng)用的簡(jiǎn)單示例:
圖片
可以通過(guò)運(yùn)行以下命令快速探索它是如何工作的:
cargo install generate
cargo install trunk
cargo generate --git https://github.com/yewstack/yew-trunk-minimal-template
trunk serve --open
上面的代碼片段將生成一個(gè)樣板代碼,可以用它作為Yew應(yīng)用程序的起始模板。安裝Trunk的原因是因?yàn)閅ew使用Trunk捆綁器來(lái)為web提供HTML。
Perseus
Perseus是一個(gè)Rust框架,用于構(gòu)建響應(yīng)式web應(yīng)用程序。它支持類(lèi)似于Next.js的功能,但它是為Rust生態(tài)系統(tǒng)設(shè)計(jì)的。
Perseus的響應(yīng)式系統(tǒng)由Sycamore響應(yīng)式庫(kù)提供支持,并具有對(duì)服務(wù)器端渲染(SSR)和靜態(tài)站點(diǎn)生成(SSG)的原生支持。它目前有超過(guò)2.8k的GitHub顆星。
下面是一個(gè)如何用Perseus編寫(xiě)一個(gè)簡(jiǎn)單的Hello World應(yīng)用程序的例子:
use perseus::prelude::*;
use sycamore::prelude::*;
#[perseus::main(perseus_axum::dflt_server)]
pub fn main<G: Html>() -> PerseusApp<G> {
PerseusApp::new()
.template(
Template::build("index")
.view(|cx| {
view! { cx,
p { "Hello World!" }
}
})
.build()
)
}
要開(kāi)始使用Perseus,運(yùn)行下面的命令創(chuàng)建一個(gè)示例應(yīng)用程序并啟動(dòng)服務(wù)器:
cargo install perseus-cli
perseus new my-app
cd my-app/
perseus serve -w
Sauron
Sauron是一個(gè)受Elm Architecture啟發(fā)的微型前端框架。它支持事件、狀態(tài)管理、客戶(hù)端和服務(wù)器端web開(kāi)發(fā)。一個(gè)最簡(jiǎn)單的方法來(lái)試驗(yàn)它是如何工作的是通過(guò)使用html2sauron將HTML轉(zhuǎn)換為Sauron源代碼,如下所示:
圖片
Sauron在GitHub上有超過(guò)2k顆星,對(duì)于一個(gè)新框架來(lái)說(shuō),這真是令人印象深刻,這表明人們對(duì)該框架的興趣正在增長(zhǎng)。
Dioxus
Dioxus是一個(gè)Rust UI庫(kù),可以讓你構(gòu)建響應(yīng)式跨平臺(tái)UI組件——它支持web、移動(dòng)和桌面應(yīng)用程序開(kāi)發(fā)。它借鑒了React的一些特性(包括鉤子),并使用了自己的虛擬DOM——可以把它看作是React與Rust的安全性和速度的混合體。
這是Dioxus應(yīng)用中組件的樣子:
fn app(cx: Scope) -> Element {
let result: &mut u32 = cx.use_hook(|| 0);
cx.render(rsx!(
div { "Hello World" }
))
}
Dioxus擁有強(qiáng)大的社區(qū)支持之一,在GitHub上擁有超過(guò)20k顆星。
Iced
Iced是一個(gè)跨平臺(tái)開(kāi)發(fā)GUI庫(kù),它的架構(gòu)也受到Elm架構(gòu)的啟發(fā),并提供對(duì)響應(yīng)式編程、類(lèi)型安全和速度的內(nèi)置支持。
Iced使用以下結(jié)構(gòu)來(lái)編寫(xiě)代碼:
- 狀態(tài):應(yīng)用程序的狀態(tài)
- 消息:你關(guān)心的用戶(hù)交互或有意義的事件
- 視圖邏輯:一種將狀態(tài)顯示為在用戶(hù)交互時(shí)產(chǎn)生消息的方法
- 更新邏輯:一種對(duì)消息作出反應(yīng)并更新?tīng)顟B(tài)的方法
這是一種將用戶(hù)界面劃分為不同概念的好方法,這些概念很容易推理。Iced社區(qū)也在迅速發(fā)展,GitHub上有超過(guò)2.4萬(wàn)顆星星。
Tauri
Tauri是一個(gè)基于rust的庫(kù),通過(guò)利用HTML、CSS和JavaScript等web技術(shù)為UI構(gòu)建輕量級(jí)桌面應(yīng)用程序。你可以使用任何可以編譯成HTML、CSS和JavaScript的前端框架。
與依賴(lài)于Chromium和Node.js的Electron(一個(gè)JavaScript桌面應(yīng)用開(kāi)發(fā)框架)不同,Tauri使用的是系統(tǒng)的原生web視圖。這使得的二進(jìn)制文件更小和使用更有效的資源。
可以使用Tauri框架開(kāi)發(fā)一個(gè)從前端到后端邏輯的全棧桌面應(yīng)用程序。Tauri也擁有強(qiáng)大的社區(qū)支持,擁有超過(guò)81k個(gè)GitHub顆星。
后端Web框架
后端開(kāi)發(fā)是web開(kāi)發(fā)中關(guān)注服務(wù)器端的一個(gè)方面,典型的后端框架包括數(shù)據(jù)庫(kù)管理、會(huì)話(huà)處理、模板、ORM和數(shù)據(jù)庫(kù)遷移等功能,用于構(gòu)建和維護(hù)可靠的web應(yīng)用程序。
Rocket
Rocket是一個(gè)流行的Rust異步web框架,它簡(jiǎn)化了開(kāi)發(fā)。它抽象了web開(kāi)發(fā)的許多潛在復(fù)雜性,因此你可以專(zhuān)注于使用用戶(hù)友好的API構(gòu)建主要業(yè)務(wù)邏輯,而不會(huì)影響安全性和速度。
作為最早的Rust框架之一,它在GitHub上擁有超過(guò)24k顆星。
下面是一個(gè)簡(jiǎn)單的Rocket服務(wù)器示例,它接受兩個(gè)查詢(xún)參數(shù)并返回一個(gè)Happy Birthday消息:
#[macro_use] extern crate rocket;
#[get("/<name>/<age>")]
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是一個(gè)基于參與者模型的后端Web框架,可以構(gòu)建大規(guī)模復(fù)雜的Web應(yīng)用程序。雖然它很復(fù)雜,但它公開(kāi)了底層實(shí)現(xiàn)以支持進(jìn)一步的定制。
下面是一個(gè)簡(jiǎn)單的Happy Birthday API的例子,使用Actix Web來(lái)了解它是什么樣子的:
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
}
它有一個(gè)龐大的開(kāi)發(fā)者社區(qū),在GitHub上擁有超過(guò)21k顆星。
Axum
Axum是一個(gè)現(xiàn)代的、異步優(yōu)先的web框架,建立在流行的Tokio生態(tài)系統(tǒng)之上,旨在構(gòu)建可擴(kuò)展和可維護(hù)的web應(yīng)用程序。
Axum是一個(gè)非常健壯的web框架,但它并沒(méi)有暴露太多底層實(shí)現(xiàn)以避免復(fù)雜性,因?yàn)樗噲D對(duì)社區(qū)中的新開(kāi)發(fā)人員更友好,所以與Actix相比,你不會(huì)看到很多可怕的泛型,因?yàn)樗橄罅似渲械囊恍Kδ軓?qiáng)大,支持許多現(xiàn)代web api,如HTTP/2、WebSockets等。
與Actix Web相比,Axum讓初學(xué)者更容易構(gòu)建中間件,這是我認(rèn)為Axum最好的特性之一。
下面是一個(gè)簡(jiǎn)單的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的社區(qū)規(guī)模很大,而且還在不斷增長(zhǎng),在GitHub上擁有超過(guò)18.3k顆星。
Warp
Warp的設(shè)計(jì)是快速、輕量級(jí)和可組合的,開(kāi)始使用它并開(kāi)始構(gòu)建高性能api是很容易的。
為了進(jìn)一步說(shuō)明使用Warp是多么容易,這里有一個(gè)簡(jiǎn)單的API,模仿我們一直在使用的相同的Happy Birthday示例。它現(xiàn)在看起來(lái)短了很多,但仍然很容易理解:
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上有超過(guò)9.5k顆星,它的開(kāi)發(fā)者社區(qū)還在繼續(xù)增長(zhǎng)!
Tide
Tide是一個(gè)小型框架,類(lèi)似于Express.js (Node.js)、Sinatra (Ruby)和Flask (Python),用于快速開(kāi)發(fā),異步構(gòu)建web應(yīng)用程序。它擁有在大多數(shù)成熟的web框架中可以找到的大部分功能,包括路由、認(rèn)證、套接字、日志、模板引擎、中間件、測(cè)試和其他實(shí)用程序。
下面是一個(gè)簡(jiǎn)單的Happy Birthday應(yīng)用程序:
use tide::Request;
async fn birthday(_req: Request<()>) -> tide::Result<String> {
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,這是為了異步實(shí)現(xiàn)的速度和安全性而構(gòu)建的,它在GitHub上也有大約5k顆星。
比較最流行的Rust web后端框架
Actix、Rocket、Axum和Warp都是流行的Rust web框架,每個(gè)框架都有自己獨(dú)特的功能和優(yōu)勢(shì)。下面讓我們仔細(xì)看看它們的共同點(diǎn):
非阻塞IO
Actix、Rocket、Axum和warp都使用Rust的async/await語(yǔ)法為web應(yīng)用程序提供非阻塞I/O操作。這允許更好的性能和可伸縮性,因?yàn)榭蚣芸梢酝瑫r(shí)處理多個(gè)請(qǐng)求而不會(huì)阻塞或減慢速度。
中間件
中間件是web框架中的一個(gè)常見(jiàn)特性,它允許開(kāi)發(fā)人員在請(qǐng)求-響應(yīng)周期中添加功能,例如日志記錄、身份驗(yàn)證和錯(cuò)誤處理。所有最流行的Rust web框架——Actix、Rocket、Tide和warp都支持中間件。
WebSocket
它們都支持WebSocket,但是使用WebSocket的具體語(yǔ)法和特性可能因框架而異,因此框架的選擇將取決于項(xiàng)目的具體需求。
高并發(fā)性
Actix和Axum可能更適合需要高并發(fā)性和高性能的應(yīng)用程序,而Rocket和warp可能更適合優(yōu)先考慮易用性和靈活性的應(yīng)用程序。