使用 Yew 构建 Rust 前端 - 第一部分
乌姆普斯季节
乌姆普斯季节
在本系列文章中,我们将学习如何使用Yew重现经典的“捉妖巫师 (Hunt the Wumpus) ”游戏。原版游戏是在命令行上进行的,而我们将使用网页。Yew 允许我们用 Rust 定义前端。我们的应用将被编译为WebAssembly以供执行。
这个应用需要这个吗?不需要。
有应用需要这个吗?尚有争议,但很有可能。欢迎在评论区留言讨论!
我们到底会不会做?当然会!
这是一个入门级的教程——熟悉 Rust 会很有帮助,但这里没有太多花哨的内容。熟悉任何命令式语言就足够了。
我把这篇文章分成了三个部分。第一部分旨在作为你开始一个空白项目的实用指南。暂时不要开始寻找乌姆普斯,只需将填充文本替换成适合你应用的内容即可。第二部分设置了我们的基本 UI 和在洞穴中移动的机制,第三部分讨论了游戏逻辑。
编辑:您可以在这里播放已完成的应用程序!
设置
Rust 有一些很棒的工具,让编译流程相对轻松。cargo-web
我们使用的 Yew 只是其中一种。如果您喜欢这里的内容,我接下来推荐您阅读RustWasm 一书。它将引导您构建一个 Game of Life<canvas>
应用程序,无需使用任何复杂的框架或工具——您可以在此基础上选择所需的功能。您可以决定使用它的底层或高层级。另外,也请务必查看draco,这是一个替代的客户端 Rust->Wasm 框架。
你需要一个夜间 Rust 编译器。如果需要,可以参考rustup入门 - 很简单。你还需要cargo-web
:cargo install cargo-web
安装完成后,导航到你的项目目录,并cargo new hunt-the-wumpus
在终端中执行 issue。用你选择的文本编辑器打开该文件夹。我们将首先添加一些内容,以确保所有内容能够编译和运行。
首先,让我们设置项目文件夹以使用内置的 Rust 目标。执行以下命令:
$ rustup override set nightly
$ echo 'default-target = "wasm32-unknown-unknown"' > Web.toml
这将确保cargo web
命令始终使用正确的目标。该rustup override
命令特定于目录 - 要全局更改它,请使用rustup default nightly
。我更喜欢默认使用 stable 版本,仅在必要时使用 nightly 版本。
现在让你的Cargo.toml
外观如下所示:
[package]
authors = ["Hunter Wumpfrey <hw@bottomlesspit.net>"]
edition = "2018"
name = "hunt-the-wumpus"
version = "0.1.0"
[[bin]]
name = "hunt"
path = "src/main.rs"
[dependencies]
stdweb = "0.4"
[dependencies.yew]
version = "0.9.2"
[lib]
name = "hunt_the_wumpus"
path = "src/lib.rs"
我们的大部分代码都将存在于库中,而二进制文件只是将应用程序安装到页面上。
main.rs
接下来用以下内容替换您的:
extern crate hunt_the_wumpus;
extern crate yew;
use hunt_the_wumpus::Model;
use yew::prelude::App;
fn main() {
yew::initialize();
let app: App<Model> = App::new();
app.mount_to_body();
yew::run_loop();
}
这个存根会找到我们的挂载点,并将我们的程序挂载到上面。说到这儿,我们来创建一个挂载点。问题:
$ mkdir static
$ touch static/index.html
我们也只需要一个存根。将以下内容添加到该文件并保存:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Hunt the wumpus!">
<meta name="author" content="YOU">
<title>HUNT THE WUMPUS</title>
<link rel="stylesheet" type="text/css" href="hunt.css">
<script src="hunt.js"></script>
</head>
<body>
</body>
</html>
我们不需要再用它了——它只会加载我们编译好的 JS 和样式表。这个static
目录也是你的图标存放的地方——我喜欢这个。
现在,让我们添加基本的紫杉轮廓——我们要渲染的东西。问题:
$ touch src/lib.rs
使用以下模板填充:
extern crate stdweb;
#[macro_use]
extern crate yew;
use yew::prelude::*;
pub struct Model {
arrows: u8,
}
#[derive(Debug, Clone)]
pub enum Msg {}
impl Component for Model {
type Message = Msg;
type Properties = ();
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self {
Model { arrows: 5 }
}
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
true
}
}
impl Renderable<Model> for Model {
fn view(&self) -> Html<Self> {
html! {
<div class="hunt",>
<div class="header",>{"Hunt the Wumpus"}</div>
<div class="body",>
<span class="arrows",>{&format!("Arrows: {}", self.arrows)}</span>
</div>
</div>
}
}
}
这就是我们大多数组件的样子。如果你用过其他前端框架,应该会觉得它看起来有些熟悉。它有一个Component
trait,我们可以在其中定义状态转换,例如create
和update
,还有一个Renderable<T>
trait,它使用类似 JSX 的html!
宏来定义视图。然后,它借鉴了 Elm 等工具的灵感,提供了一种Msg
类型来驱动update
方法中的事件。我们目前还没有任何消息需要处理,所以只包含一个存根。一开始,update
它会始终返回true
,ShouldRender
并触发重绘。
在开始编码之前,我们需要设置其余的构建管道。毕竟,我们要用它yarn
——毕竟它是一个 Web 应用。
$ yarn init
// answer the questions
$ yarn add -D @babel/core @babel/preset-env autoprefixer node-sass nodemon npm-run-all postcss postcss-cli rollup rollup-plugin-babel rollup-plugin-postcss rollup-plugin-uglify rollup-plugin-wasm serve
然后将这些脚本添加到您的package.json
:
"scripts": {
"build:js": "rollup -c",
"build:rs": "cargo web deploy --release",
"build:scss": "node-sass --include-path scss scss/hunt.scss css/hunt.css",
"build:css": "postcss --use autoprefixer -o static/hunt.css css/hunt.css",
"build:style": "run-s build:scss build:css",
"build:copy": "cp target/deploy/hunt.css release/ && cp target/deploy/hunt.wasm release/ && cp target/deploy/index.html release/ && cp target/deploy/favicon.ico release/",
"build": "run-s clean:deploy build:rs build:js build:style build:copy",
"clean:deploy": "rm -rf /release",
"prod": "run-s build serve",
"serve": "serve -p 8080 release",
"watch:rs": "cargo web start --release",
"test": "echo \"Error: no tests!\" && exit 1"
},
要设置我们的应用程序范围的样式表,请发出:
$ mkdir scss
$ touch scss/hunt.scss
为了确保一切连接正常,请输入以下内容:
.arrows {
font-weight: bold;
}
现在,让我们按下大按钮。打开你的终端并输入
$ yarn build:style
$ yarn watch:rs
最后,将浏览器指向localhost:8000
。您应该会看到以下内容:
猎杀 Wumpus
箭:5
一切就绪!开发配置已生效。接下来,让我们完成以下配置.gitignore
:
/target
**/*.rs.bk
/node_modules
yarn-*.log
/css
/static/*.css
/release
让我们测试一下我们的生产包。首先创建rollup.config.js
并保存以下内容:
import babel from "rollup-plugin-babel"
import uglify from "rollup-plugin-uglify"
export default {
input: './target/deploy/hunt.js',
output: {
name: 'hunt',
file: './release/hunt.js',
format: 'es',
},
plugins: [
babel({
exclude: 'node_modules/**'
}),
uglify
]
};
现在请确保退出该watch:rs
过程,然后尝试yarn prod
。构建完成后,您应该在 处看到相同的输出localhost:8080
。
一旦一切正常,就提交!git init && git commit -m "Initial commit
“
请参阅此处第 1 部分末尾的完整代码。
如果您已准备好继续构建,请参阅第 2 部分。
文章来源:https://dev.to/decidously/lets-build-a-rust-frontend-with-yew---part-1-3k2o