前言
Rust 作为最近几年连续霸榜爆火的语言,虽然也知道其在前端基建领域逐渐得到了广泛应用,但同时又因其学习难度等因素,让很多人望而却步。
所以,在此整理了一下Rust在前端领域的一些基本场景与应用,以及相关框架的一些入门使用,但是并不会包含太多的Rust语法,目的就是为了前端小伙伴儿们能够快速入门了解这门语言,以及其在前端领域是如何发挥作用的。
写作不易,如果这篇文章对您有所帮助,欢迎 关注♥️ + 点赞👍 鼓励一下作者,感恩~
Rust发展历程
2006年,软件开发者Graydon Hoare在Mozilla工作期间,开始了Rust作为一个个人项目。根据他在麻省理工技术评论的一次采访,Rust的灵感来自于Hoare公寓楼里一个坏掉的电梯。电梯操作系统的软件崩溃了,Hoare意识到这类问题通常源于程序如何使用内存的问题。
通常,这些类型设备的软件是用C或C++编写的,但这些语言需要大量的内存管理,可能导致系统崩溃的错误。因此,有一种说法,在内存不安全的语言中,高达70%的安全漏洞都是由于内存安全问题造成的。因此 Hoare着手研究如何创建一种既紧凑又无内存错误的编程语言。
Mozilla 于2009年开始赞助这个项目,并且在2010年首次公开。也在同一年,其编译器源代码开始由原本的 OCaml 语言转移到用 Rust 语言,进行自我编译工作,称作“rustc”,并于2011年实际完成。这个可自我编译的编译器在架构上采用了 LLVM 作为它的后端。
第一个有版本号的Rust编译器于2012年1月发布。Rust 1.0是第一个稳定版本,于2015年5月15日发布。
2021年2月8日,AWS、华为、Google、微软以及 Mozilla 宣布成立Rust基金会,并承诺在两年时间里每年投入不少于 100 万美元的预算,以用于 Rust 项目的开发、维护和推广
根据Rust 最新官方新闻,谷歌日前宣布向 Rust 基金会捐款 100 万美元,这笔资金将用于改善 C++ 与 Rust 互操作性。谷歌当前正在使用 Rust 语言重写在 Linux 核心之外的 Android 关键安全组件,从而进一步减少安全漏洞。而在 Android 13 中,就已经有约 21%的新原生代码使用 Rust 语言开发。
Rust 特点
Rust语言作为一种更底层的编程语言,作用类似于c与c++等底层语言,设计时注重安全性、并发性和性能,并且力求提供高效的内存管理,而不牺牲开发者的生产力,与之对应的就是Javascript,Go,Python等高级语言或者应用语言。
以下是Rust的一些关键特点:
- 内存安全:无需手动进行垃圾回收,同时,也不需要像Js这种有自动垃圾回收机制,这样可以进一步提高性能。其核心是 使用 所有权(ownership)来管理内存。每个值有一个所有者,且每个值只能有一个所有者。所有权的转移、借用和生命周期等规则确保了内存的自动管理而不依赖垃圾回收。
- 零成本抽象:Rust 提供的高级抽象(如迭代器、闭包、泛型等)通常不会引入额外的性能开销。编译器会对这些抽象进行优化,确保在最终生成的机器码中没有额外的运行时开销。
- 并发性:Rust 通过其所有权模型来确保并发编程的安全。Rust 在编译时会捕捉到潜在的并发错误,例如数据竞争(data races)和并发访问的冲突。同时,供了异步编程支持(
async/await),可以在不阻塞线程的情况下进行并发操作,从而提升应用程序的响应性和性能。
这里从前端Javascript的角度对比说一下Rust在内存管理这块的特点:
- C语言:性能高,但是开发者需要手动管理内存,极容易出现内存错误,例如:微软估计,其代码中70%的bug都是由于内存错误引起的。
- Javascript:有自动垃圾回收(GC)机制,不需要用户手动管理,会在数据不再被引用时自动回收。但是由于引入了垃圾回收器,性能也会变低。
- Rust:结合了两者的优势,既不需要手动管理内存,同时又可以保证性能,
总结:Rust 是从性能角度来说,是一门接近 C/C++ 的低级语言,但同时又提供了现代语言的高级特性,因此又可以做很多应用层的开发,比如:前端页面,后端服务等。
注意:以上特点描述过程中,可能包含很多Rust中的专业概念,我们可以暂时先不需要理解,后期慢慢学习.
Web Assembly
在认识Rust之前,从前端的角度来说,我们要首先了解Web Assembly,因此他们Rust之所以在前端领域能够发挥这么大的作用,其核心就是依赖 Web Assembly。
认识WASM
关于 Web Assembly(WASM),我们需要知道以下几点:
- 首先,WebAssembly是一门新的编程语言,它于2019年12月5日正式成为与HTML、CSS以及JavaScript 并列的web领域第四类编程语言。
- 其次,WebAssembly是"汇编语言"而不是高级语言,程序员不直接编写WebAssembly代码,而是通过特殊的编译器将高级语言转换成WebAssembly代码。
- 再次,WebAssembly是预处理过后的二进制格式,它实际是一个IR(Intermediate Representation)!类似Java的ByteCode或者.Net的MSIL/CIL。
- 最后,WebAssembly是web上的语言,这意味着主流的浏览器可以读取并且执行它。
最后简单总结,Web Assembly 作为一个语言比较特殊,不需要用户手动编写,而是通过编写更高级语言,例如:rust,然后通过“特殊的编译器”生成WebAssembly二进制代码,最终WebAssembly代码再被一个嵌入在浏览器里的"特殊的虚拟机"执行。这就是WebAssembly的全部工作过程。
为什么需要WebAssembly?
在web领域,我们已经有了JavaScript这样利器,但美中不足的是JavaScript的性能不佳,即使可以通过第二章里提到的各种编译优化来解决一部分问题,但在类似图形图像处理、3D游戏、AR、VR这些高性能应用的场景下,我们似乎任然需要一个更好的选择。 那就是 WebAssembly。
“快”是相对的,目前我们可以认为在运行速度上:原生C/C++代码 > WebAssembly > asm.js > 原生JavaScript。
其中,有几点要了解:
- asm.js 为什么比原生Javascript快呢?asm.js的实现去掉大部分的自动GC机制,然后改成了强类型语言,编译器能够更大程度地进行优化。
- WebAssembly与JavaScript运行性能详细对比:整体上我认为可以描述为“很快,但是不够快”。也就是说,我们期望它比JavaScript快非常多,快个10倍或者8倍,但实际上只能快一点点,大概也就是不到2倍左右
在浏览器端运行 WebAssembly代码
我们通过一段简单的代码,可以快速体验一下,如何在浏览器端直接运行WebAssembly代码。
-
打开任意的浏览器,例如Chrome。
-
按F12,启动开发者工具。
-
找到Console页签,复制这一段代码,回车运行。
WebAssembly.compile(new Uint8Array(` 00 61 73 6d 01 00 00 00 01 0c 02 60 02 7f 7f 01 7f 60 01 7f 01 7f 03 03 02 00 01 07 10 02 03 61 64 64 00 00 06 73 71 75 61 72 65 00 01 0a 13 02 08 00 20 00 20 01 6a 0f 0b 08 00 20 00 20 00 6c 0f 0b`.trim().split(/[\s\r\n]+/g).map(str => parseInt(str, 16)) )).then(module => { const instance = new WebAssembly.Instance(module) const { add, square } = instance.exports console.log('2 + 4 =', add(2, 4)) console.log('3^2 =', square(3)) console.log('(2 + 5)^2 =', square(add(2 + 5))) })这里我们是通过直接手写二进制机器码的方式生成了一段wasm代码,并使用了WebAssembly.compile接口来进行编译,最后调用了wasm实现的add和square函数。如果顺利的话,你的浏览器会编译这段WebAssembly代码并调用执行,输出对应的计算结果,具体如下图所示:
Web端应用场景
- 【Google-可视化】谷歌地球3D地图 www.google.com/intl/zh-CN/…
- 【Bilibili-编解码】哔哩哔哩视频网站 member.bilibili.com/platform/up…
- 【Figma-设计工具】Figma在线UI设计 www.figma.com/:Figma可以说是典型的WebAssembly应用了,使用了zaplib(一款基于wasm和Rust的高性能web应用框架)来进行开发。外围的交互操作还是用原生的JS+CSS+HTML来实现的,中间核心绘图区域是一个由wasm+webGL来驱动的的canvas模块。
- 【Adobe-设计工具】Photoshop Web版:www.adobe.com/express/fea…
- 【FFmpeg-音视频处理】ffmpeg.wasm github.com/ffmpegwasm/…
最后,WebAssembly在服务端也会很多的应用场景,具体可以参考上面的文档。
以上内容参考自文档:zhuanlan.zhihu.com/p/620767652,如需进一步了解,该文档中对于 WebAssembly 会有更详细的介绍。
Rust vs Javascript
由于前端对于Javascript及其生态是最熟悉的,因此,这里我们通过对比的形式,可以快速理解Rust中常见工具的作用及应用场景。
| Javascript/Nodejs | Rust | |
|---|---|---|
| 官网 | Javascript官网 | rust官网 |
| 类型系统 | 动态弱类型语言 | 静态强类型语言 |
| 包管理工具 | Npm,Yarn | Cargo |
| 包管理仓库 | Npm registry | Crates.io |
| 构建工具 | Webpack/Vite | Cargo:Rust内置构建工具 |
| 依赖管理 | package.json/package-lock.json | Cargo.toml/Cargo.lock |
| 编译器 | Js没有传统意义的编译器,类似Ts中的tsc | rustc:Rust内置编译器 |
| 版本管理工具 | nvm:Nodejs版本管理工具 | rustup:Rust内置版本工具 |
-
在实际开发中,我们只需要使用
cargo即可,cargo new 目录:初始化rust项目cargo run:运行rust代码cargo build:编译生成目标文件。cargo install: 安装rust依赖。cargo uninstall: 卸载rust依赖。
Rust 与 WebAssembly
上面我们提到,WebAssembly 不需要我们手动编写,实际开发中,就需要一门源语言,我们只需要编写源语言,然后借助相应的编译器将其转换成WebAssembly即可。
而Rust就是一门非常适合的源语言,Rust 生态天然支持 WebAssembly,并且有专门的生态去跟踪和优化WebAssembly。
那在实际开发中,如何快速使用Rust进行开发,并且编译生成WebAssembly呢?这里介绍两个工具:
- rust-webpack:通过 Webpack 来打包 Rust 编译的 WebAssembly 文件,更侧重于将 Rust 集成到现有的 Webpack 构建流程中,适用于已经使用 Webpack 的项目。
- wasm-pack:更专注于从 Rust 到 WebAssembly 的编译过程,并提供便捷的 JavaScript API 和 NPM 发布功能,适用于 Rust 开发者构建 WebAssembly 模块并与前端 JavaScript 进行交互。
Wasm-Pack脚手架的使用可以参考文档:rustwasm.wasmdev.cn/docs/wasm-p…
Rust 应用场景
前端构建工具
前端构建工具有许多,而且层出不穷,各自有不同的特点、优势以及应用场景。
按照类型,我们主要从 编译工具 和 打包工具 两个方面去分析对比一下:
- 编译工具:这类工具主要专注于将源代码转成目标代码,比如:处理Javascript的兼容性和语法转换。
- 打包工具:这些工具不仅处理代码转换,还负责打包和优化项目资源。
编译工具
| 编译工具 | 传统方案 | 基于 Rust 实现 |
|---|---|---|
| Javascript编译器 | Babel:基于Javascript实现 | Swc |
| Css预编译器 | Sass/Less:基于Dart实现 | Sass-rs |
| Postcss | postcss-rs:比 Postcss 快 20x 倍 | |
| Stylus | ||
| CSS-in-JS | ||
| 代码格式化 | Prettier | dprint:比 Prettier 快 30x 倍 |
打包工具
| 传统方案 | 基于 Rust 实现 | |
|---|---|---|
| JS编译器和打包工具 | Rollup | Rolldown |
| Esbuild(go语言实现) | ||
| Parcel | Parcel2 | |
| 综合构建工具 | Vite | |
| Webpack | Turbopack | |
| 构建工具全家桶 | Rome : 前端构建全家桶 | |
| biome:Rome的继任者 | ||
- Parcel: 特色主打零配置并且开箱即用,Parcel2 使用rust进行了重写,性能进一步提升。
- Vite 在生产环境中使用 Rollup 进行打包构建,开发环境中,使用 Esbuild 进行快速构建和热更新代码等。这样会导致开发与生产环境构建行为差异,以及源代码被不同的工具重复解析,导致大量可以避免的开销。
- Rolldown:是由Vite团队实现,Rust编写,目标是是为Vite设计,提供超级快的构建速度,从而替换Rollup与Esbuild。
- Turbopack: 由 Webpack 的创建者 Tobias Koppers 和 Next.js 团队使用 Rust 编写,开发的一个前端模块化的工具,按作者构想 Turbopack 的目标是取代 Webpack。官方宣称 TurboPack 的速度比 Vite 快 10 倍,比 Webpack 快 700 倍。
- Rome: 是一个新的 JavaScript/TypeScript 工具链,旨在统一和简化前端开发中的多个任务。它的设计目标是成为一个全面的工具集,整合 构建工具、代码格式化、代码检查、linting、打包、转译 等功能,并且这些功能全部用Rust重写,而不是集成现有的插件。
- Rome已于23年9月份,facebook宣布已停止维护,后续衍生了一个新的产品,Biome,要做的事情和Rome类似。
前端页面开发
| 基于 Javascript 实现 | 基于 Rust 实现 |
|---|---|
| React / Vue | Yew: 整个 Web 应用都基于 Rust 开发, Leptos |
| 传统构建方案: | wasm-pack:直接将你的 Rust 代码打包成 npm 包 wasm-bindgen:促进 WebAssembly 模块和 JavaScript 之间的高级交互,通常与 wasm-pack 配合使用 cargo-web:集成 Rust WebAssembly 编译和前端开发支持的工具 |
| 推荐构建方案 | Trunk:一个专为 Rust 和 WebAssembly 项目设计的构建工具 |
- 使用Rust进行前端开发的核心是通过Rust编译成WASM在浏览器端等运行,因此,实际开发语言也是使用Rust,不像其他使用Rust实现的构建工具,底层实现是Rust,工具的使用者依然是使用JS,TS等前端语言。
- 传统构建方案:在没有Trunk之前,我们通常是借助:
wasm-pack,`wasm-bindgen,等工具来完成将Rust代码 编译为 WebAssembly,然后借助carg-web完成前端静态资源的打包优化,以及构建本地开发环境等。 - Trunk:一个专为 Rust 和 WebAssembly 项目设计的构建工具,它简化了 WebAssembly 项目的构建和打包过程,自动化了将 Rust 代码编译为 WebAssembly、将静态资源(如 HTML、CSS、图片等)打包和优化,并提供开发者友好的工作流。
桌面应用开发
| 基于 Nodejs 实现 | 基于 Rust 实现 | |
|---|---|---|
| 桌面实现方案 | Electron | Tauri |
| 编辑器 | Vscode | Zed |
- Electron和Tauri底层是用了不同的语言,但是对于框架的使用者而言,依然是是用JS,TS等前端语言。
- Tauri 是目前最流行的 Electron 替代方案,通过使用 Rust 和 Webview2 成功解决了 Electron 的包体积大和内存占用高的问题,因为它不需要 Chromium 浏览器,而是使用轻量级的 Webview 来显示 Web 内容。因此,Tauri非常适合那些需要轻量、高效、跨平台的桌面应用程序,尤其适用于对应用体积和性能有较高要求的开发者。
- Atom 团队也是看到了 Tauri 的成功,才决定基于 Rust 去做 Zed 编辑器
服务器端开发
| 基于 c++ 实现 | 基于 Rust 实现 | |
|---|---|---|
| 底层语言 | Nodejs | Deno |
| 服务端框架 | Expressjs | Rocket Axum |
| Node拓展 | 用 C++ 开发的 Node.js 扩展 | Napi-rs:Rust 和 N-API 开发高性能 Node.js 拓展 |
其他场景
-
区块链
- 由于其高性能、内存安全和并发性,Rust 在区块链开发中变得非常流行。Rust 是构建 Polkadot 和 Substrate 等区块链协议的首选语言。
- Rust 可以用于编写区块链的核心引擎、共识算法、智能合约等部分。
-
游戏开发
- Rust 在游戏开发中的应用逐渐增多,尤其是在性能要求极高的底层开发部分。例如,游戏引擎 Amethyst 就是用 Rust 编写的。
-
高性能计算(HPC)
- 由于 Rust 可以直接操作底层硬件,提供精细的内存控制,它也适用于高性能计算领域,例如金融建模、科学计算、模拟等。
总结:
从上面我们可以看到Rust应用场景非常广泛,下到操作系统,再到命令行工具,再到web开发,再到服务器端开发,似乎无所不能,其实总结起来主要两点:
- Rust 本质上是类似 C与C++ 等底层语言,可以做很多c和c++的工作,并且实现起来更简单更安全。
- 同时Rust 又可以像Go 等相关高级语言一样,支持高并发,做很多web与服务器端的工作。
- 同时又可以借助WASM,做很多浏览器端的开发。
Rust - helloworld
首先,我们通过一个helloworld例子,感受一下rust的基本使用。
-
安装rust,配置环境
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-
初始化一个rust项目
cargo new helloworld -
使用
cargo build编译项目,生成一个target目录,如下:默认通过
cargo build编译生成的文件会包含调试信息,除此之外,我们可以通过cargo build -- release去生成文件体积更小,性能更好的二进制。 -
执行main.rs文件,输出
Hello world!./target/debug/helloworld也可以直接使用命令:
cargo run // 本质上也是运行./target/debug/helloworld 这个二进制文件就会输出
Hello world!。
Trunk - helloworld
我们可以借助Yew,Trunk等工具,实现使用rust进行web页面的开发。依然是通过demo案例来体会。
-
配置环境
// 1. 安装rust // 2. 安装Trunk:类似于webpack,只不过它是基于rust创建wasm应用程序的构建工具, 更多细节可以参考官网https://trunkrs.dev/ cargo install --locked trunk
-
创建一个rust项目
cargo new trunk-helloworld -
在根目录下创建 index.html,index.scss 等,也可以创建其他资源文件。
// index.html <html> <head> <link data-trunk rel="scss" href="./index.scss" /> </head> <body></body> </html>// index.scss html { body { background-color: green; } }注意:Trunk构建时内部默认支持 dart-sass, 因此我们才可以在根目录直接使用scss文件。
4 . 执行trunk build,会在根目录下生成dist文件,里面包含相关打包生成的前端文件,如下:
我们可以看到在 index.html文件中,通过<script type="module"> 引入了相关.wasm文件。 这也是rust进行前端开发的核心思路:将rust代码编译成wasm文件,然后再通过<script type="module">在html中引入wasm模块。
-
执行
trunk serve,开启本地服务,然后就可以通过localhost:8080访问页面啦
Yew - helloworld
Trunk的作用是 将rust代码编译成wasm 的过程进行了简化,但是具体如何用rust代码写前端页面呢?这就要靠**Ye w 框架了,可以把类比于Vue React等前端框架,它也提供了组件化的开发模型,支持声明式 UI,响应式编程,并允许开发者使用 Rust 的类型系统和性能优势来构建浏览器应用。**
-
初始化 rust 项目
cargo new yew-helloworld -
安装 yew 依赖
cargo add yew --features "csr"yew不会默认指定特性,我们做的是 web 端开发,所以指定开启csr。其他的还包括 ssr - 服务端渲染;hydration - 混合开发,支持客户端、服务端渲染。 -
在根目录下创建 index.html,index.scss 等,也可以创建其他资源文件。
// index.html <html> <head> <link data-trunk rel="scss" href="./index.scss" /> </head> <body></body> </html> // index.scss html { body { background-color: green; } } -
修改
src/main.rs文件use yew::prelude::*; #[function_component(App)] fn app() -> Html { html! { <h1>{"hello, trunk/yew!"}</h1> } } fn main() { yew::Renderer::<App>::new().render(); } -
执行
trunk serve --open开启本地服务,通过localhost:8080即可访问,效果如下:
常见问题
-
cargo install 如果遇到超时或者443问题,一般是由于默认rust镜像仓库是在国外,比较慢,需要修改成国内的仓库地址。
具体解决方式:
cd ~/.cargo目录下,新建config文件,配置如下内容:[source.crates-io] registry = "https://github.com/rust-lang/crates.io-index" replace-with = 'ustc' [source.ustc] registry = "https://mirrors.ustc.edu.cn/crates.io-index" #registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git" [http] check-revoke = false
参考文档
- Rust 在前端领域的应用
- 前端研发的新基础设施 - Rust ️️
- MDN-编译 Rust 为 WebAssembly
- 用 Rust 和 N-API 开发高性能 Node.js 扩展
- rust前端web开发框架yew使用
总结
通过这篇文章,相信大家对Rust,以及Rust在前端领域的应用有了一个初步的体会与认识:
- Rust依靠其高性能的优势,在前端基建领域正逐渐形成全面的替换,我们大家以前常用的构建工具,在Rust领域都有其相应的对标工具,不过目前传统构建工具其生态丰富,应用量依然巨大。
- Rust借助WASM,可以实现直接用Rust去开发前端页面,但是传统Vue,React 开发方式依然占据主导地位,Rust更多是搭配Wasm,实现一些性能要求比较高的前端页面。
- Rust在服务器端,桌面端等其他领域都有广泛应用。