WebAssembly简介
WebAssembly(简称Wasm)是一种新型的编程语言,它可以在网页浏览器中运行。WebAssembly的设计目标是提供一种新的代码格式,使得开发者可以使用高级编程语言(如C、C++、Rust等)编写的程序在浏览器中直接运行,而无需转换成JavaScript。这样做的好处是可以提高应用程序的执行效率,因为WebAssembly代码可以直接在浏览器中运行,而无需经过JavaScript引擎的解释过程。
WebAssembly
WebAssembly的二进制格式比JavaScript文本文件小得多,因此下载速度更快,这在网速较低的情况下尤为重要。WebAssembly的解析和执行速度也更快,因为它是静态类型的,引擎在编译期间不需要类型推断,大多数优化都是在编译源代码期间,在浏览器执行之前进行的。此外,WebAssembly的内存管理类似于C和C++,不需要垃圾收集,这也有助于提高性能。
WebAssembly与JavaScript之间是一种协作互补的关系。WebAssembly可以在某些场景中弥补JavaScript性能不足的短板,而想要在Web浏览器中使用WebAssembly,我们也离不开相关JavaScript API提供的帮助。WebAssembly可以与JavaScript代码交互,这意味着开发者可以使用WebAssembly来处理需要更高计算能力的任务,例如图像处理、游戏和虚拟现实等。
JavaScript
WebAssembly的应用场景广泛,包括游戏开发、图形图像处理、音视频处理、非JavaScript程序的移植等。例如,Unity和Unreal Engine等游戏引擎已经支持将游戏引擎编译成Wasm格式,并在浏览器中运行。此外,WebAssembly还可以用于网页游戏、数据可视化、图像处理、图形渲染等图形图像领域,以及Web播放器、在线教育、视频会议、直播、点播等音视频领域。
总的来说,WebAssembly为Web应用程序提供了一种新的性能优化手段,使得开发者可以在保持Web应用程序的可移植性和安全性的同时,提高应用程序的执行效率。
web-sys简介
web-sys 是一个用于 Rust 编程语言的 crate,它提供了访问 Web API 的方式,使得 Rust 代码能够在浏览器环境中运行。通过 web-sys,Rust 开发者可以直接调用 JavaScript 的 Web API,从而实现与 HTML、CSS 和 JavaScript 的交互。
web-sys 允许 Rust 代码操作 DOM(文档对象模型),例如创建和修改 HTML 元素、处理事件等。此外,它还支持与 WebGL、Canvas、Audio、Video 等多媒体相关的 API,以及与网络通信相关的 API,如 Fetch API。
使用 web-sys 时,通常需要通过 wasm-bindgen crate 来进行绑定生成,以便在 Rust 代码中使用 JavaScript 的 Web API。wasm-bindgen 负责将 Rust 类型转换为 JavaScript 类型,并生成相应的绑定代码。
在使用 web-sys 时,开发者需要在 Cargo.toml 文件中声明依赖,并根据需要启用特定的功能(features)。例如,如果需要使用 console 对象,就需要在 features 中添加 console。
web-sys 是构建 WebAssembly 应用程序时常用的工具之一,它有助于 Rust 代码与现代 Web 技术的无缝集成。
环境配置
安装rust编译器
安装nodejs二进制文件
! nodejs二进制下载后,选择存放目录后解压并配置环境变量
项目目录结构
代码案例:rust与javascript交互案例
./Cargo.toml
[workspace] members = [ "rust_project", ]
./rust_project/Cargo.toml
[package] name = "rust_project" version = "0.1.6" authors = ["name"] description = "A sample project with wasm-pack" license = "MIT/Apache-2.0" repository = "https://github.com/yourgithubusername/hello-wasm" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] crate-type = ["cdylib"] [dependencies] wasm-bindgen = "0.2.92" futures = { version = "0.3.30", features = ["thread-pool"] } [dependencies.web-sys] version = "0.3.69" features = [ "console" ]
./rust_project/lib.rs
extern crate wasm_bindgen; use wasm_bindgen::prelude::*; //调用外部函数 #[wasm_bindgen] extern { pub fn alert(s: &str); } #[wasm_bindgen] extern "C" { // Use `js_namespace` here to bind `console.log(..)` instead of just // `log(..)` #[wasm_bindgen(js_namespace = console)] fn log(s: &str); // The `console.log` is quite polymorphic, so we can bind it with multiple // signatures. Note that we need to use `js_name` to ensure we always call // `log` in JS. #[wasm_bindgen(js_namespace = console, js_name = log)] fn log_u32(a: u32); // Multiple arguments too! #[wasm_bindgen(js_namespace = console, js_name = log)] fn log_many(a: &str, b: &str); } // 提供外部调用的函数 #[wasm_bindgen] pub fn greet(name: &str) { alert(&format!("Hello, {}!", name)); } #[wasm_bindgen] pub fn add(a: i32, b: i32) -> i32 { a + b } //web assembly初始化时自动执行 #[wasm_bindgen(start)] pub fn run() { bare_bones(); using_a_macro(); using_web_sys(); } fn bare_bones() { log("Hello from Rust!"); log_u32(42+58); log_many("Logging", "many values!"); } // Next let's define a macro that's like `println!`, only it works for // `console.log`. Note that `println!` doesn't actually work on the wasm target // because the standard library currently just eats all output. To get // `println!`-like behavior in your app you'll likely want a macro like this. macro_rules! console_log { // Note that this is using the `log` function imported above during // `bare_bones` ($($t:tt)*) => (log(&format_args!($($t)*).to_string())) } fn using_a_macro() { console_log!("Hello {}!", "world"); console_log!("Let's print some numbers..."); console_log!("1 + 3 = {}", 1 + 3); } // And finally, we don't even have to define the `log` function ourselves! The // `web_sys` crate already has it defined for us. fn using_web_sys() { use web_sys::console; console::log_1(&"Hello using web-sys".into()); let js: JsValue = 4.into(); console::log_2(&"Logging arbitrary values looks like".into(), &js); }
./web_project/index.js
const js = import("./node_modules/@name/rust_project/rust_project.js"); js.then((js) => { js.greet("WebAssembly"); }); js.then((js) => { const result = js.add("1, 2"); console.log(`The result from Rust is: ${result}`); });
./web_project/index.html
hello-wasm example
./web_project/package.json
{ "scripts": { "serve": "webpack-dev-server" }, "dependencies": { "@name/rust_project": "^0.1.6" }, "devDependencies": { "webpack": "^4.47.0", "webpack-cli": "^3.3.12", "webpack-dev-server": "^3.11.3" } }
./web_project/package.config.js
const path = require("path"); module.exports = { entry: "./index.js", output: { path: path.resolve(__dirname, "dist"), filename: "index.js", }, mode: "development", };
执行方式
接下来,在命令行中运行 npm adduser:
bash
> npm adduser Username: yournpmusername Password: Email: (this IS public) you@example.com
你需要完善你的用户名,密码和邮箱。如果成功了,你将会看到:
bash
Logged in as yournpmusername on https://registry.npmjs.org/.
构建包
现在我们已经完成了所有配置项,开始构建吧!在命令行输入以下命令:
bash
wasm-pack build --scope rust_project
把我们的包发布到 npm
把我们的新包发布到 npm registry:
bash
cd pkg npm publish --access=public
让我们离开pkg目录,并创建一个新目录site,尝试以下操作:
bash
cd ../.. mkdir web_project cd web_project
npm install npm run serve
这将启动一个 Web 服务器。访问 http://localhost:8080,你应该会在屏幕上看到一个内容为 Hello, WebAssembly! 的警告框。我们已经成功地从 JavaScript 调用了 Rust,并从 Rust 调用了 JavaScript。
还没有评论,来说两句吧...