Rust + WebAssembly 新手完全入门指南
Rust WebAssembly 新手完全入门指南这篇文章面向前端、Rust 开发者只要跟着步骤就能跑通你的第一个 WebAssembly 前端组件。WebAssembly 是什么WebAssembly简称 Wasm是一种可在现代浏览器中运行的低级、紧凑、高效的二进制指令格式。它的出现主要是用来解决 JavaScript 天生的性能瓶颈尤其是计算密集型场景下WebAssembly 能达到接近原生的执行性能。可以说WebAssembly 的出现使得在网页上运行高级、复杂的客户端应用如图像编辑、Web AI 推理、复杂的游戏引擎成为可能。通过 caniuse我们可以看到 WebAssembly 在主流浏览器中已经广泛可用如下图所示环境准备首先确保你已经安装好 Nodejs 和 Rust 环境。这里我们会用到 wasm-packwasm-pack是 Rust Wasm 开发的核心工具负责构建、打包、测试 Wasm 项目。# 安装 wasm-packcargoinstallwasm-pack接下来我们使用wasm-pack初始化项目# 初始化项目wasm-pack new wasm-examplecdwasm-examplewasm-pack会帮我们生成如下的目录结构.├── Cargo.toml ├── LICENSE_APACHE ├── LICENSE_MIT ├── README.md ├── src │ ├── lib.rs │ └── utils.rs └── tests └── web.rswasm-pack初始化项目时默认使用的是 wasm-pack-template 这个模板由于缺少维护所以默认使用的Edition、wasm-bindgen 等的版本都比较低你可以手动调整下但是在这个案例中我们就暂时不动它们了。在以后的开发中你可以维护一个自己的模板然后通过如下命令使用模板wasm-pack newname--templatetemplate实现一个简单 Wasm 组件我们首先实现一个简单 Wasm 组件我们将会用到 js-sys 这个库它包含 JavaScript 语言本身的 API如数组、字符串、console、Promise 等。# 添加 js-syscargoaddjs-sys现在我们直接修改src/lib.rs文件# 默认模板里有 src/utils.rs这里引入了它modutils;usewasm_bindgen::prelude::*;#[wasm_bindgen]pubfnsum_array(arr:js_sys::Array)-u32{letmutsum0;foriin0..arr.length(){letvalarr.get(i).as_f64().unwrap_or(0.0)asu32;sumval;}sum}#[wasm_bindgen]属性宏声明了将导出sum_array函数以供 JS 调用这就是我们这个简单组件提供的能力。接下来我们进行编译wasm-pack build--targetweb编译完成后我们可以在pkg目录中看到编译结果pkg ├── package.json ├── README.md ├── wasm_example_bg.js ├── wasm_example_bg.wasm ├── wasm_example_bg.wasm.d.ts ├── wasm_example.d.ts └── wasm_example.jswasm_example_bg.wasm是核心的 Wasm 二进制文件包含我们编写的 Rust 逻辑wasm_example.js是 JS 胶水代码负责 Wasm 的加载、类型转换把 Rust 函数封装成 JS 可直接调用的方法wasm_example.d.ts是 TypeScript 类型定义用于支持 TS 项目。这里的--target web表示我们的目标编译平台是 web这样方便在 HTML 文件中引入。在根目录创建index.html并编辑!DOCTYPEhtmlhtmllangenheadmetacharsetUTF-8metanameviewportcontentwidthdevice-width, initial-scale1.0titleRust WebAssembly/title/headbodyscripttypemoduleimportinit,{sum_array}from./pkg/wasm_example.js;awaitinit();console.log(求和结果为,sum_array([10,20,30]));/script/body/html由于浏览器的安全策略不允许加载本地 Wasm 模块所以无法使用file://协议打开 HTML 文件我们需要一个本地 HTTP 服务器来启动项目。npx serve.这时候打开浏览器的控制台就能够看到打印出来的求和结果了。使用 Rust 操作 DOM借助 web-sys我们可以直接用 Rust 操作 DOM。与js-sys不同web-sys包含浏览器环境提供的 Web API。cargoaddweb-sys--featuresWindow,Document,HtmlElement这里需要注意的是web-sys必须指定启用的feature不然编译不通过。现在我们通过web-sys来修改网页标题编辑src/lib.rs添加#[wasm_bindgen]pubfnset_title(title:str){// 1. 获取 window 对象letwinmatchweb_sys::window(){Some(w)w,Nonereturn,};// 获取 document 对象letdocmatchwin.document(){Some(d)d,Nonereturn,};// 修改网页标题doc.set_title(title);}重新编译完成后我们修改index.html添加scripttypemoduleimportinit,{set_title,sum_array}from./pkg/wasm_example.js;awaitinit();console.log(求和结果为,sum_array([10,20,30]));set_title(Hello world);/script刷新网页后我们就能够看到网页的标题被修改为Hello world了。接入 Vite在实际开发中我们很少直接写原生 HTML基本上是基于 Vite、Webpack 等构建工具进行开发这里以最常用的 Vite 为例演示如何集成 Rust Wasm。npmcreate vitelatest wasm-vite-example ----templatevanilla-tscdwasm-vite-example把之前的wasm-example项目整个拷贝到wasm-vite-example的根目录。在实际开发中这种时候肯定是要用 monorepo 的但在这个案例中就不这么弄了一切从简。.├── .gitignore ├── index.html ├── node_modules ├── package-lock.json ├── package.json ├── public ├── src ├── tsconfig.json └── wasm-example安装插件npminstall-Dvite-plugin-wasm-pack创建vite.config.ts并编辑import{defineConfig}fromvite;importwasmPackfromvite-plugin-wasm-pack;exportdefaultdefineConfig({plugins:[wasmPack(./wasm-example)]});接下来在src/main.ts中添加上我们之前写的业务逻辑如下importinit,{set_title,sum_array}fromwasm_exampleasyncfunctioninitWasm(){awaitinit();console.log(求和结果为,sum_array([10,20,30]));set_title(Hello world);}initWasm();启动开发服务npmrun dev打开浏览器就能看到 Wasm 函数的执行结果了。结尾至此我们就成功实现了第一个 WebAssembly 前端组件虽然它很简陋没有涉及到测试与调试如用wasm-pack test进行单元测试、使用浏览器 DevTools 调试 Wasm 代码Wasm 高级特性如共享内存、多线程、SIMD 指令等性能优化与踩坑。不过没有关系这些内容在后续的文章更新中可能会涉及到。现在我们需要做的是动手实现一遍这个简单的 Wasm 组件。毕竟对于新手而言最好的学习方式就是动手实践。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2440094.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!