2023年,Rust能干掉JavaScript吗?

2023-05-28 0 855

原副标题:2023年,Rust能杀掉JavaScript吗?

作者 | Josh Mo

翻译者 | 原子武器果汁

策画 | 地信

如果大家早已拥有一定的 Rust Web 开发经验,应该听说过在后端 Web 开发上用 Rust(通过 WASM)还是用 Java 这个充满著讽刺性的热门话题。不少人坚持不懈表示反对,认为 Rust“不适宜生产”,而且速度“比 Java 还慢”。

这种讲法也有规矩:从历史上看,因为 WASM 封禁 DOM,所以从 Java 初始化 WASM 的确会产生附加开支。但目前这点的影响早已极小,计算方法数据显示,像 Leptos 和 Dioxus 这样的 Rust WASM 架构(下层使用 Sledgehammer,属于速度前十强等级的 Java 架构)在操控性上早已强于 React 和 Vue 等大部分 JS 架构。钟爱的朋友能参照原初计算方法测试。

2023年,Rust能干掉JavaScript吗?

如相片亲见,各架构按操控性次序分别为原初 Java、Sledgehammer(Dioxus 的下层发动机)、wasm-bindgen(容许 WASM 组件和 Java 实现互操作性的库)、Solid.js ,Vue 和 RxJS,之后是 Leptos、Dioxus、LitJS,接下去是 Sycamore……排在其前的才是 Vue 和 React(还有 Yew)。很显著,其中一些 Rust 后端架构即使比最盛行的 Java 架构操控性说实话。可别抬杠说也能不用架构,直接撰写纯 Java 标识符——的确能,但这显著偏移责任编辑探讨的主轴了。

TechEmpower 发布的后端操控性计算方法测试:

在前 10 大后端架构中,有 5 个是用 Rust 撰写的。很显著,Rust 在后端架构领域占有着突出的优势,即使能与 C++ 反面对决。有人可能会说 Rust 用于后端服务项目有点太过了——但它的确能带来更高操控性,挤占的缓存更小、服务项目的运行灵活性更快、引起崩盘的可能性也更低。那些都是不可高估的关键不利因素,毕竟从企业的视角来看,尽量节省成本在我看来高错误率事宜。

但也要承认,在优先选择新架构时,速度和常规性操控性往往并足以构成综合重大决策的充分不利因素。开发人员新体验如何、错误处理功能是否强悍、怎样解决 SSR 问题等也都非常关键。要想做出合情合理的最终优先选择,要先为那些问题找到合理标准答案。幸运的是,Rust 同样是有备而来。

开发人员新体验

不管大家主观判断如何,在 Web 开发方面,Rust 有着相对宽松的使用要求。其中很多标识符的样式上跟 React 等 Web 架构中的 Java 组件非常相似——比如 Leptos(一款 Rust Web 架构)中的组件标识符:

use leptos::*;

#[component]pub fn SimpleCounter(cx: Scope, initial_value: i32) -> impl IntoView{// create a reactive signal with the initial valuelet(value, set_value) = create_signal(cx, initial_value);

// create event handlers for our buttons// note that `value` and `set_value` are `Copy`, so its super easy to move them into closures// (for reference: closures are like anonymous/arrow functions in Java)letclear = move |_| set_value(0);letdecrement = move |_| set_value.update(|value| *value -= 1);letincrement = move |_| set_value.update(|value| *value += 1);

// create user interfaces with the declarative `view!` macroview! {cx,<div><button on:click=clear>“Clear”</button><button on:click=decrement>“-1”</button><span>“Value: “{value} “!”</span><button on:click=increment>“+1”</button></div>}}

// Easy to use with Trunk (trunkrs.dev) or with a simple wasm-bindgen setuppub fn main() {mount_to_body(|cx| view! { cx, <SimpleCounterinitial_value=3/> })}

能看到,那些标识符其实跟 JSX 区别不大,最大的不同就是该组件不返回任何内容,而是用 Rust 宏来渲染 HTML。其 main 函数类似于 React、Vue 乃至其他 JS 架构当中作用于 root 文件的 index.js 脚本。再来看另一个来自 Dioxus 的例子:

// An example of a navbarfn navbar(cx: Scope) -> Element {cx.render(rsx! {ul {// NEWLink { to: “/”, “Home”}br {}Link { to: “/blog”, “Blog”}}})}

// An example of using URL parametersfn get_blog_post(id: &str) -> String{match id {“foo”=> “Welcome to the foo blog post!”.to_string(),“bar”=> “This is the bar blog post!”.to_string(),id=>format!(“Blog post {id} does not exist!”)}

能看到,RSX(相当于 Dioxus 中的 React JSX)的撰写非常简单,即使可能比使用 Leptos 还简单一些。而且很显著,React 的组件设计理念早已超越了特定编程语言,在 Rust 这边也早已有所体现。大家即使能把那些函数跟单元结构体(unit structs)结合起来,为各种函数提供命名空间,这样就能实现对 API 初始化之类的捆绑了,例如:

// this is a unit structpub struct APICalls;

// we can implement the unit struct to bundle functions under it// like so:Impl APICalls {pub asyncfn get_dog_api_data() -> Json<Dog> {… some code here// this should probably return some json data}pub asyncfn get_cat_api_data() -> Json<Cat> {… some code here// this should probably return some json data}}

fn navbar (cx: Scope) -> Element {// now we can call the data like this, or something similarletdogs = APICalls::get_dog_api_data().await;}

如大家亲见,哪怕只是稍稍触及 Rust 的浅表层次,也早已能够获得相当不错的开发效果。而且真正让人眼前一亮的,还要数 Rust 的consequences机制,这也是其强于 Java 即使是 Type 的关键亮点之一。通常,如果使用 Type 进行编码,我们只有两个优先选择:类型检查和 try-catch 块。但对于拥有一定开发经验的朋友们来说,不断把代友打包到 try-catch 块中仍然有其隐患。毕竟 Type 仍可被编译为 Java,所以一旦不小心就会引起跟 JS 相关的问题(CJS 和 ECMA 兼容问题,运行时内随时可能出现的随机错误等)。

下面来看看 Rust 的基本错误处理机制:

asyncfn foo() -> Result<String, String>{letbar = String::from(“foobar!”);// return is implicit, no need to write “return”match bar.trim() {“foobar!”=> Ok(bar),_ => Err(“Was not foobar!”.to_string())}}

#[tokio::main]fn main() -> Result<String, String> {letOk(res) = foo().await else{returnErr(“Was not foobar :(“.to_string());}

println!(“The string was: {res}!”);}

这里展示了两个示例:我们能使用基础模式匹配来确定字符串是什么,如果结果匹配则返回 OK;如果属于其他内容(会加注下划线),则只返回一个具有 String 类型的错误(也会提示 std::error::Error -,我们能将其作为错误类型来处理)。我们还能声明一个变量,要求该变量要是实际的 Result 类型,否则执行其他操作(在示例中为提前返回)。之后,我们就能使用 res 本体了,因为它将被声明为 Result 中包含的值。

生态系统

虽然 Java 的生态系统(Node/npm)要比 Rust 庞大得多,但 Rust 阵营也完全能够满足大多数项目的需求。Rust 目前对数据库、Redis 和 Web 应用程序中所需的各种服务项目都提供良好支持,不管用哪种编程语言都能使用。

如果您打算构建 SaaS,Rust 正好准备了几乎包罗万象的工具箱:用于 SMTP 的 lettre、用于 Stripe 支付的 async-stripe,用于处理社交网络账户登录的 OAuth 回调 oauth2,用于数据库(即使是 airtable)的 SQLx(如果倾向于对象关系映射,还有 Diesel 或 SeaORM 能优先选择)。当然,还有用于 GPT-3 的 openai_api。在 SaaS 投入运行之后,Rust 即使支持用于 RabbitMQ 的 lapin 和用于 Kafka 的 rs-rdkafka。由此看来,如果大家想开发一项坚如磐石的高操控性服务项目,Rust 的表现完全能跟 Java 反面抗衡。

根据个人经验,我发现 cargo 在对接各种工具时表现突出。以 clippy 为例,这是一款无需初始化就能使用的出色工具程序,只要输入 cargo clippy 即可启用,它能检测出不必要的借用等部分、帮助我们快速优化标识符。更关键的是,如果需要把一个项目中的配置迁移至另一项目,也能直接在根目录下创建一个 clippy.toml 文件并随意加以配置。

由于 Rust 本身并不是普及度最高的 Web 编程语言,所以生态系统中各厂商对它的支持态度可能没那么积极,比如开放相应服务项目 API。但因为大多数服务项目 API 采取的都是 HTTP REST Web 服务项目的形式,所以 Rust 也能用得起来,大家还能使用 reqwest 等工具检索自己需要的数据。

部 署

在部署方面,Shuttle 是迄今为止最简单的 Rust 部署方法。后端部署的确要麻烦一点,要么需要鼓捣配置文件、要么通过网站上的 GUI 添加环境变量来接入需要使用的服务项目,或者是提供相应的静态文件。

Shuttle 的另一个优点就是采取基础设施即标识符的实现理念,能通过标识符注释快速上手。只需简单通过 Rust 宏在 main 函数中声明,大家就能避免亲自动手鼓捣配置文件。我们能借此交付数据库并支持静态文件,从能够编译为静态资产的 Next.js、React 等 JS 架构处添加编译后端,例如:

// main.rs#[shuttle_runtime::main]pub async fn axum (#[shuttle_shared_db::Postgres] postgres: PgPool,#[shuttle_secrets::Secrets] secrets: SecretStore,#[shuttle_static_folder] static: PathBuf) -> shuttle_axum::ShuttleAxum {// carry out database migrations (this assumes migrations are idempotent)sqlx::migrate!().run(&postgres).await.expect(“Migrations failed :(“);

let hello_world = secrets.get(“MY_VARIABLE”).expect(“Is MY_VARIABLE set in Secrets.toml?”);

// Make a router serving API routes that require a DB connectionlet api_router = create_api_router(postgres);

// Add a compiled frontend (like e.g. from Next.js, React, Vue etc) to the routerlet router = Router::new().nest(“/api”, api_router).nest_service(“/”, get_service(ServeDir::new(static).handle_error(handle_error));

// Rust returns implicitly so writing “return” is not requiredOk(router.into())}

总 结

综上所述,Rust 无疑是一款值得用于 Web 开发的优秀语言。凭借着缓存挤占小、性能水平高、正常运行时间长和运维成本低等优势,Rust 将帮助您在后端领域节省下宝贵的时间和金钱。

原文链接:

https://joshuamo876.bearblog.dev/can-rust-beat-java-in-2023/

声明:责任编辑为 InfoQ 翻译,未经许可禁止转载。

今日好文推荐

比Python快35000倍!LLVM&Swift之父宣布全新编程语言Mojo:编程被颠覆了

拼多多回应将总部从中国迁至爱尔兰;微软Bing爆炸级更新,文生图原生支持中文;75岁人工智能教父离职谷歌,痛悔毕生工作| Q资讯

谷歌、OpenAI 都白干,开源才是终极赢家!谷歌内部文件泄露:欲借开源打败 OpenAI

谷歌用机器人大规模删除标识符:二十多年积累了数十亿行,已删除5%C++标识符

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务