Rust 在 Web 上的应用
原文发表于我的博客
“我们能用 Rust 创建 Web 应用吗?” ——很多人问过。我也是。
我开始学习 Rust 的主要目标是从我的 ducky JavaScript 技术栈(Node.js Express)转向 Rust,也就是说,用 Rust 制作 Web 应用程序。
一年过去了,我学到了一些东西。所以我写了这篇文章,分享我的 Rust Web 编程心得。
使用 Rust 创建 Web 应用程序的方法有很多,例如,将 Rust 代码编译为客户端 JavaScript、编写 RESTful API,或者像 2012 年一样构建同构 Web 应用程序。我将一一介绍。
Rust 中的客户端 JavaScript
我首先想到的是像 React 那样基于组件的架构。这意味着你需要找到一种在 Web 浏览器上运行 Rust 代码的方法。
感谢 ASM.js 和 WebAssembly,这成为可能,通过快速设置,您可以在几分钟内将 Rust 代码编译为 ASM.js/WebAssembly。
现在,对于基于组件的架构,我刚刚创建了一些宏来包装stdweb包并通过浏览器的 DOM API 呈现 HTML 元素。
https://github.com/huytd/rust-webapp-template/blob/master/src/main.rs#L13-L58
如果你觉得我刚刚发布了一种外星语言,不要害怕。component!
宏用于定义自定义元素。mount_component!
宏用于将元素附加到文档,html!
宏用于从 HTML 字符串创建元素。
以下是我的使用方法:
component!(AppComponent => {
init: {
let e: Element = html!("
<div>
<p>
<span>Hello</span>
<span>World</span>
</p>
<GreenButton />
</div>
");
let mut button = GreenButton::new();
mount_component!(e, "GreenButton", button);
e
},
render: |this: &Element| {
}
});
component!(GreenButton => {
init: {
let button = document().create_element("button");
button.add_event_listener(move |_: ClickEvent| {
js! {
alert("Yo! This is the Green Button!");
}
});
button
},
render: |this: &Element| {
this.set_text_content("This is a button");
}
});
fn main() {
stdweb::initialize();
let mut app = AppComponent::new();
mount_component!(document(), "#root", app);
stdweb::event_loop();
}
onClick
当你甚至可以在 Rust 代码中编写事件时,谁还需要 React 呢:D(开个玩笑)。
您可能需要查看整个项目以详细了解如何使用stdweb
这些宏。
Rust 中的 RESTful API
如果您不想放弃 JavaScript 前端,这是更好的方法:只需用 Rust 编写一个 API 服务器即可使其与您现有的前端协同工作。
市面上有很多框架可供选择。我们来看看AreWeWebYet。
对于喜欢更精简框架的人来说,tiny_http是最好的选择。
为了简单起见,您可以使用nickel.rs,它是 Rust 中最轻量级的框架之一,受到 Node 的 Express 启发。
对于 HTTP/2 支持,solicit是您目前唯一的选择。
就我个人而言,我更喜欢使用Rocket,因为它是一个非常优秀的框架,功能丰富,代码简洁,语法优雅。它最近还添加了内置的 TLS 支持。这个框架唯一的缺点是需要使用 Rust Nightly 版本。
GET
这是中方法的简单路由处理程序Rocket
。
#[get("/posts", format = "application/json")]
fn get_posts(page: i64) -> Json<Value> {
Json(json!({
"result": []
}))
}
我通常让它Rocket
为我提供静态文件,就像我在 Express 中所做的那样:
#[get("/")]
fn index() -> io::Result<NamedFile> {
NamedFile::open("www/index.html")
}
#[get("/<file..>", rank = 5)]
fn files(file: PathBuf) -> Option<NamedFile> {
NamedFile::open(Path::new("www/").join(file)).ok()
}
这样我就可以把所有前端代码都放在www
这个文件夹中,并通过 RESTful API 访问。例如,一个典型的项目结构如下:
├── Cargo.toml
├── README.md
├── src
│ ├── main.rs
│  └── ...Rust code here...
└── www
├── index.html
├── main.js
├── package.json
├── webpack.config.js
└── ...JavaScript code here...
要使用数据库,最好使用Diesel。
如果你想看到一个Rocket
++项目Diesel
的实际运行,我会毫不羞愧地在这里React
插入我的一个附带项目及其在 Github 上的源代码。
如果它对您来说足够好,请随意查看或使用它。
Rust 中的同构 Web 应用程序
最后一个,也是我最喜欢的一个,就像是 2012 年,我的第一份 PHP 工作开始了我的编程生涯。
不再有单页应用程序,不再有客户端渲染的 UI。不再有因浏览器 JavaScript 禁用而导致的网页崩溃。
Rocket
许多其他框架都具有在绑定一些数据后呈现 HTML 模板的能力。
#[get("/")]
fn index() -> Template {
let news = fetch_from(RSS_URL).ok().expect("Could not read RSS");
Template::render("index", &news)
}
我最近使用+模板构建了一个Hacker News 阅读器,您可以在这里查看它的源代码(嘿,我知道,这又是一次无耻的 PR)。Rocket
Handlebars
如果你正在问“Rust 能做 Web 吗?” ,希望我列出的三种方法能够对你有所帮助。每种方法都有其优缺点,具体方法取决于你的项目,你可以选择其中一种,也可以混合使用。
请随时在Hacker News或Reddit上发表评论来分享您的想法。
文章来源:https://dev.to/huytd/rust-for-the-web-55