使用Rust增强JS
使用Rust增强JS
Javascript是目前全世界使用最广的语言(TIOBE排行榜比较迷,JS并没有排在第一位,我个人并不认同它的排名)。在过去这么多年中,围绕着Javascript已经建立了庞大的基础设施生态:例如:
- 使用
webpack来将多个js文件打包成一个 - 使用
Babel允许你用现代化的js语法编写兼容旧浏览器的代码 - 使用
Eslint帮助开发找出代码中潜在的问题,类似cargo clippy。
以上的种种都在帮助js成为更好的语言和工具,它们是Web应用程序得以顺利、高效的开发和运行的基石。这些工具往往使用Javascript语言编写,一般来说,是没有问题的,但是在某些时候,可能会存在性能上的瓶颈或者安全隐患,因此阴差阳错、机缘巧合下,Rust成为了一个搅局者。
Javascript基建库
deno
首先出场的自然是咖位最重的之一,可以说正是因为deno和swc的横空出世,才让一堆观望的大神对于Rust实现Javascript基建有了更强的信心。
deno是node半逆转后的字序,从此可以看出deno是Node.js的替代,它的目标是为Typescript/Javascript提供一个更现代化、更安全、更强大 的运行时,同时内置了很多强大的工具,可以用于打包、编译成可执行文件、文档、测试、lint等。
值得一提的是,deno的不少工具都使用了swc进行建造,包括代码审查、格式化、文档生成等。
通过包引入的方式来对比下deno和node,大家可以自己品味下。
// node
const koa = require("koa");
const logger = require("@adesso/logger")
// deno
import { Application } from "https://deno.land/x/oak/mod.ts";
import { Logger } from "https://adesso.de/lib/logger.ts"swc
swc是Typescript/Javascript编译器,它可以用来编译、压缩和打包JS,同时支持使用插件进行扩展,例如做代码变换等。
swc目前正在被一些知名项目所使用,包括Next.js,Parcel和Deno,还有些著名的公司也在使用它,例如Vercel、字节跳动、腾讯等。
它的性能非常非常高,官方号称,在单线程下比Babel快20倍,在4核心下比Babel快70倍!
几个使用案例:

官方还提供了一个在线运行的demo,功能齐全,可以试试。

Rome
Rome可以用来对JavaScript、TypeScript、HTML、JSON、Markdown 和 CSS 进行lint、编译、打包等功能,它的目标是替代Babel、ESLint、webpack、Prettier、Jest等。
一开始Rome是使用Typescript开发,目前正在用Rust进行重写。有趣的是: Rome的作者也是Babel的作者, 后者还是他在学习编译原理时做的。
fnm
fnm是一个简单易用、高性能的Node版本管理工具,还支持.nvmrc文件(nvm的node版本描述文件)
boa
boa是一个高性能的javascript词法分析器,解析器和解释器,目前还是实验性质的。

napi
napi可以用于构建基于Node API的Nodejs插件,目前由nextjs主导开发。
volt
volt是一个现代化的、高性能、安全可靠的Javascript包管理工具。目前该库正处于活跃开发阶段,只供学习使用。

neon
neon可以用于写安全、高性能的原生Nodejs模块。
fn make_an_array(mut cx: FunctionContext) -> JsResult<JsArray> { // 创建一些值: let n = cx.number(9000); let s = cx.string("hello"); let b = cx.boolean(true); // 创建一个新数组: let array: Handle<JsArray> = cx.empty_array(); // 将值推入数组中 array.set(&mut cx, 0, n)?; array.set(&mut cx, 1, s)?; array.set(&mut cx, 2, b)?; // 返回数组 Ok(array) } register_module!(mut cx, { cx.export_function("makeAnArray", make_an_array) })
resvg-js
resvg-js是一个高性能svg渲染库,使用Rust + Typescript实现。下面的图片通过svg实现(羞~~~):
deno_lint
deno_lint, 由deno团队出品的lint工具,支持Javascript/Typescript,支持Deno也支持Node。
优点之一就是极致的快:
[
{
"name": "deno_lint",
"totalMs": 105.3750100000002,
"runsCount": 5,
"measuredRunsAvgMs": 21.07500200000004,
"measuredRunsMs": [
24.79783199999997,
19.563640000000078,
20.759051999999883,
]
},
{
"name": "eslint",
"totalMs": 11845.073306000002,
"runsCount": 5,
"measuredRunsAvgMs": 2369.0146612000003,
"measuredRunsMs": [
2686.1039550000005,
2281.501061,
2298.6185210000003,
]
}
]rslint
rslint是一个高性能、可定制性强、简单易用的Javascript/Typescript lint分析工具。
$ echo "let a = foo.hasOwnProperty('bar');" > foo.js
$ rslint ./foo.js
error[no-prototype-builtins]: do not access the object property `hasOwnProperty` directly from `foo`
┌─ ./foo.js:1:9
│
1 │ let a = foo.hasOwnProperty('bar');
│ ^^^^^^^^^^^^^^^^^^^^^^^^^
│
help: get the function from the prototype of `Object` and call it
│
1 │ let a = Object.prototype.hasOwnProperty.call(foo, 'bar');
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
│
╧ note: the method may be shadowed and cause random bugs and denial of service vulnerabilities
Outcome: 1 fail, 0 warn, 0 success
help: for more information about the errors try the explain command: `rslint explain <rules>`rusty_v8
rusty_v8是v8的Rust语言绑定,底层封装了c++ API。
用WASM增强JS
wasm
wasm(web assembly) 是一种低级语言,它运行在浏览器中,可以和javascript相互调用,几乎所有浏览器都支持, 而且目前有多种高级语言都可以直接编译成wasm,更是大大增强了它的地位。
目前来说Rust可以编译成wasm,虽然还不够完美,但是它正在以肉眼可见的速度快速发展中。因此同时使用Rust和Javascript成为了一种可能:将Rust编译成wasm,再跟js进行交互,两者共生共存,各自解决擅长的场景(wasm性能高,js开发速度快)。
yew
yew是一个正在活跃开发的Rust/Wasm框架,用于构建Web客户端应用。

gloo
[gloo]是一个模块化的工具,使用Rust/WASM构建快速、可靠的Web应用。
use gloo::{events::EventListener, timers::callback::Timeout};
use wasm_bindgen::prelude::*;
pub struct DelayedHelloButton {
button: web_sys::Element,
on_click: events::EventListener,
}
impl DelayedHelloButton {
pub fn new(document: &web_sys::Document) -> Result<DelayedHelloButton, JsValue> {
// 创建 `<button>` 元素.
let button = document.create_element("button")?;
// 监听button上的`click`事件
let button2 = button.clone();
let on_click = EventListener::new(&button, "click", move |_event| {
// 一秒后,更新button中的文本
let button3 = button2.clone();
Timeout::new(1_000, move || {
button3.set_text_content(Some("Hello from one second ago!"));
})
.forget();
});
Ok(DelayedHelloButton { button, on_click })
}
}wasm-bindgen
wasm-bindgen可以让WASM模块和Javascript模块进行更好的交互。
use wasm_bindgen::prelude::*;
// 从Web导入 `window.alert` 函数
#[wasm_bindgen]
extern "C" {
fn alert(s: &str);
}
// 从Rust导出一个`greet`函数到Javascript,该函数会`alert`一条欢迎信息
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}wasm-pack
wasm-pack是一站式的解决方案,用于构建和使用Rust生成的WASM,支持在浏览器中或后台的Node.js中与Javascript进行交互。

wasmer
wasmer是业界领先的WASM运行时,支持WASI和Emscripten。
$ wasmer qjs.wasm
QuickJS - Type "\h" for help
qjs > const i = 1 + 2;
qjs > console.log("hello " + i);
hello 3wasmtime
wasmtime是一个为WASM设计的JIT风格的独立运行时。
fn main() {
println!("Hello, world!");
}$ rustup target add wasm32-wasi
$ rustc hello.rs --target wasm32-wasi
$ wasmtime hello.wasm
Hello, world!trunk
trunk是一个WASM构建、打包、Web发布工具。
photon
photon是高性能的、跨平台的图片处理库,使用Rust开发,编译成WASM运行,为你的Web应用和Node.js应用提供无与伦比的图片处理速度,当然,它既然使用Rust开发,也可以作为一个库被你的后台程序所使用。

tinysearch
tinysearch是一个搜索工具,用于静态网站中的内容搜索,使用Rust和WASM构建。优点是体积小(适用于浏览器)、性能高、全文索引。

wasm-pdf
wasm-pdf通过Javascript和WASM来生成PDF,可以直接在浏览器中使用。
makepad
makepad是一个充满创意的Rust开发平台,支持编译成wasm,并使用webGL进行渲染。

Rust + Javascript学习教程
wasm-book
wasm-book是一本讲述Rust和wasm的书,篇幅不算长,但是值得学习,还包含了几个很酷的例子。
wasm-learning
wasm-learning是一个英文教程,用于学习Rust, wasm和Node.js,你可以学会如何使用Rust来为Nodejs构建函数,可以同时利用Rust的性能、wasm的安全性和可移植性、js的易用性。
rust-js-snake-game
rust-js-snake-game是一个用rust + js + wasm构建的贪食蛇游戏。