- 开发工具
【免费下载链接】wasm-bindgen
Facilitating high-level interactions between Wasm modules and JavaScript
wasm-bindgen仓库的 guide/src/examples/index.md 是官方示例子章节的入口文档,它并不讲解某个单一 API,而是系统性地介绍wasm-bindgen、js-sys、web-sys三大 crate 的示例集合:示例在哪里、如何运行、如何构建、以及如何将 Rust + WebAssembly 产物部署到不同环境。本文以该文档为主体骨架,结合仓库中 examples 目录下的真实工程(源码、package.json、webpack 配置)与 部署指南,把「阅读示例 → 本地运行 → 理解构建目标 → 选择部署方案」这条完整链路讲透,帮助读者快速上手并动手修改自己的示例工程。
示例集合是什么:三大 crate 的实战用法
仓库中wasm-bindgen、js-sys和web-sys三个 crate 分别承担不同职责:
wasm-bindgen:提供#[wasm_bindgen]属性宏、wasm_bindgen::prelude、JsValue等核心设施,负责 Rust 类型与 JavaScript 类型之间的桥接;js-sys:封装 ECMAScript 标准库对象(Array、Promise、Date、JSON等);web-sys:封装 Web API(DOM、Canvas、WebGL、WebRTC、Web Audio 等,仓库 web-sys/src 下即包含上千个按 WebIDL 生成的绑定模块)。
官方文档明确指出:每个示例都应附带关于它具体做了什么的信息,这正是 examples 目录中每个子工程自带 README 的原因——例如 hello_world 示例的 README 会说明构建命令和访问地址。示例覆盖了add、canvas、char、closures、console_log、dom、fetch、julia_set、paint、performance、todomvc、webaudio、webgl、webrtc_datachannel、websockets、webxr、nodejs-threads、wasm-in-wasm、without-a-bundler等数十个场景,从「最小 Hello World」到「并行光线追踪(raytrace-parallel)」「显式资源管理(explicit-resource-management)」「JSPI(jspi、jspi-fetch-streams、jspi-opfs)」均有覆盖,是学习 wasm-bindgen 各能力点的第一手资料。
阅读示例的前置条件
官方文档明确要求读者具备三样工具的知识,若还不熟悉,应先阅读入门教程:
wasm-bindgen:了解#[wasm_bindgen]宏的导入(extern "C")与导出(pub fn)机制;wasm-pack:了解如何把 Rust 工程打包成 Wasm + JS 胶水代码;- Rust + WebAssembly 项目的构建方式:了解
wasm32-unknown-unknown目标与 Cargo 的基本工作流。
如果你对这些还不熟悉,文档建议先完成Game of Life 教程(Rust 官方 RustWasm 书籍)或wasm-pack 官方教程,再回来阅读示例会顺畅得多。
获取与运行所有示例
所有示例的源码都托管在仓库中,可以下载到本地直接运行。文档给出的建议是:测试之前优先切换到最新的 release 版本,以保证示例与已发布 API 的兼容性。
注意:仓库是只读镜像,本文只介绍查看、运行与配置方式,不涉及修改仓库内容。
基于 Webpack 的示例:pnpm run serve
大多数示例都配置了 Webpack +wasm-pack,可以用pnpm run serve一键构建并启动开发服务器。这一工作流在仓库中有明确支撑:
- 根级 examples/package.json 定义了
build(pnpm run -r build)、serve(serve)、pretest(构建 wasm-bindgen CLI)等脚本; - examples/pnpm-workspace.yaml 声明
packages: - "*",即所有子目录都是 pnpm workspace 成员,并把@wasm-tool/wasm-pack-plugin、webpack、webpack-cli、webpack-dev-server等依赖统一锁定在catalog中。
以 hello_world 示例 为例,其 README 明确写着:
$ npm run serve然后浏览器访问http://localhost:8080即可看到运行效果。其工程结构正是标准「Webpack + wasm-pack」模式:
- examples/hello_world/src/lib.rs:用
#[wasm_bindgen]导入alert,并导出greet函数; - examples/hello_world/index.js:
import { greet } from './pkg'后调用; - examples/hello_world/webpack.config.js:通过
WasmPackPlugin指定crateDirectory: __dirname自动执行 wasm-pack 构建,输出到../dist/hello_world,并开启experiments.asyncWebAssembly。
如果你在仓库根目录执行,对应命令即pnpm run serve(由 examples/package.json 中serve脚本serve提供静态服务)。注意:hello_world 的 README 写成npm run serve是因为它早期使用 npm,当前仓库统一采用 pnpm workspace,实际执行应以仓库根级脚本为准。
不使用 Webpack 的示例:独立构建说明或build.sh
文档特别提到:不是所有示例都用 Webpack。不使用 Webpack 的示例会自带构建说明或build.sh脚本,例如:
- examples/without-a-bundler:README 给出
wasm-pack build --target web的构建命令,然后用任意静态服务器(http、python2 -m SimpleHTTPServer、python3 -m http.server)托管目录后访问index.html; - examples/nodejs_and_deno:package.json 中分别提供
build:nodejs(--target nodejs)、build:deno(--target deno)、build:experimental-nodejs-module、build:esm-integration等多套构建脚本; - examples/synchronous-instantiation:展示不使用 ES 模块的同步实例化方式。
此外,根级 examples/cp-dist.mjs 是一个极简的跨平台拷贝工具,被 without-a-bundler 的 postbuild 等脚本用来把index.html复制进dist目录,这也是非 Webpack 示例常用的发布手段之一。
深入理解:为什么大多数示例用 Webpack(但并非必须)
文档明确指出:大多数示例目前使用 Webpack 来组装最终产物,但这并非强制要求。原因在于wasm-bindgen的默认输出(即--target bundler)把 Wasm 模块视为原生 ES 模块来生成,而目前没有任何 JS 运行时原生实现这一模型,因此默认输出必须借助某种打包器才能消费。这个默认选择是为了顺应 JS 生态的趋势——虽然当下只有 bundler 支持把 Wasm 文件当作原生 ES 模块,但未来各工具大概率都会支持。
目前文档确认的、与wasm-bindgen完全兼容的打包器是webpack。仓库绝大多数示例都使用 webpack,并配以@wasm-tool/wasm-pack-plugin(见 examples/pnpm-workspace.yaml 的 catalog 版本锁定),详细的 webpack 配置可以直接参考 hello_world 的 webpack.config.js:
const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin"); module.exports = { entry: './index.js', output: { path: path.resolve(__dirname, '..', 'dist', 'hello_world'), filename: 'index.js', }, plugins: [ new HtmlWebpackPlugin(), new WasmPackPlugin({ crateDirectory: __dirname }), ], mode: 'development', experiments: { asyncWebAssembly: true } };部署方案总览:--target决定一切
示例的运行方式与部署方式高度耦合,而部署方法的核心就是wasm-bindgen的--target标志。下表完整列出了 部署指南 中定义的七种目标及其适用场景:
--target值 | 说明 |
|---|---|
bundler | 适合在 Webpack 等打包器中加载(默认值) |
web | 可在浏览器中直接加载(ES 模块) |
nodejs | 通过require作为 Node.js CommonJS 模块加载 |
deno | 通过 Deno 模块导入加载 |
no-modules | 类似web,但更古老,不使用 ES 模块 |
experimental-nodejs-module | 通过import作为 Node.js ESM 模块加载 |
module | 使用新的 source phase imports 语法获取编译后的 Wasm 模块 |
--target bundler:默认输出,必须配打包器
默认输出假设「Wasm 模块本身是原生 ES 模块」,但该模型尚未在任何 JS 实现中原生支持,所以必须使用打包器消费。目前唯一被确认完全兼容的打包器是 webpack,examples 中绝大多数示例(如 hello_world)都采用此方案。
--target web与--target no-modules:无打包器,浏览器直跑
如果你不使用打包器但仍在浏览器中运行,使用--target web,其要点是:
- 编译时向
wasm-bindgen传--target web; - 输出可原生包含在网页中,无需任何后处理,以 ES 模块形式引入;
web模式无法使用 NPM 依赖;- 需要查阅 浏览器支持要求,因为不会有任何 polyfill 可用。
对应的完整示例见 without-a-bundler 示例,构建命令为wasm-pack build --target web,之后用静态服务器托管即可。
--target no-modules与web类似,同样要求手动初始化 wasm、可直接嵌入网页且无需后处理,但不使用 ES 模块,属于较老的目标,示例同样参考 without-a-bundler。
--target nodejs与--target experimental-nodejs-module:Node.js 部署
--target nodejs:将 Wasm 部署进 Node.js(可作为原生模块的替代)。与「无打包器」方案一样无需任何后处理,生成的 JS shim 可以像普通 Node 模块一样被require——甚至*_bg的 Wasm 文件也有对应的 JS shim,可以直接require。要求 Node.js 8 及以上(具备 WebAssembly 支持)。--target experimental-nodejs-module:以 ES 模块方式部署进 Node.js,生成的 shim 可像普通模块一样import。要求 Node.js 12 及以上(具备 WebAssembly 与模块支持)。当前仍处于实验阶段,正式稳定前目标名可能变更。
仓库中 nodejs_and_deno 示例 的build:nodejs与build:experimental-nodejs-module脚本正是这两种目标的具体落地方案;此外还有面向 Node.js 多线程的 nodejs-threads 示例(提供test.js与test-esm.mjs两类测试)。
--target deno:Deno 部署
对 Deno 部署使用--target deno,然后在 Deno 中导入模块:
// @deno-types="./out/crate_name.d.ts" import { yourFunction } from "./out/crate_name.js";@deno-types注释让 Deno 使用生成的.d.ts类型声明。仓库 nodejs_and_deno 示例 的build:deno脚本(wasm-pack build --target deno)与之对应,其test.js通过deno run --allow-read test.js deno验证 Deno 下的运行。
--target module:source phase imports(跨工具链 ES 模块目标)
这是较新的目标,默认使用source phase imports 语法获取未实例化的 WebAssembly 模块。source phase imports 允许借助 Wasm ESM Integration,导入「编译后的 Wasm 模块(而非其实例)」:
import source wasmModule from "./module.wasm"; // 示例性用法: const instance = new WebAssembly.Instance(wasmModule, imports); export function foo () { instance.doFoo(); }该方案取代了此前需要compileStreaming以及各平台各自实现的 Wasm 加载路径。部署指南同时注明:source phase imports 目前仅 ESBuild 和 Node.js 24 支持,使用时务必确认运行环境版本满足要求。
发布到 NPM:交给wasm-pack
如果你想把编译好的 WebAssembly 发布到 NPM,文档推荐的工具是wasm-pack,其配套书籍提供了详细流程。
实战路线图:从示例到自己的工程
综合文档与仓库内容,一条完整的上手路径是:
- 挑选示例:在 examples 目录中按场景挑选(
hello_world入门、dom/canvas/webgl看 Web API、nodejs_and_deno看多目标部署、raytrace-parallel看 Worker 并行、jspi看 JSPI 新特性); - 阅读示例 README:每个示例自带说明(如 hello_world 的 README),先看它的构建命令与访问方式;
- 构建运行:Webpack 类示例在仓库根目录执行
pnpm run serve;非 Webpack 类示例按各自 README 或 package.json 脚本(如wasm-pack build --target web)构建,再用静态服务器托管; - 理解输出目标:结合 部署指南 的
--target表格判断产物适合 bundler / 浏览器 / Node.js / Deno 中的哪种环境; - 对照源码修改:例如把 hello_world/src/lib.rs 的
greet换成自己的函数,或把 without-a-bundler 的--target web换成--target nodejs,观察胶水代码差异——这正是理解 wasm-bindgen 桥接机制最直接的方式。
延伸阅读
- 官方示例文档入口:guide/src/examples/index.md
- 全部示例源码:examples/
- 部署与集成指南:guide/src/reference/deployment.md
- 浏览器兼容性要求:guide/src/reference/browser-support.md
- 开发工具
【免费下载链接】wasm-bindgen
Facilitating high-level interactions between Wasm modules and JavaScript
相关推荐
在 Wasm 里跑 Wasm:基于 wasm-bindgen 与 js-sys 实现模块嵌套实例化
在 Wasm 里跑 Wasm:基于 wasm bindgen 与 js sys 实现模块嵌套实例化 导读 本文讲解 wasm bindgen 仓库中 examp
开发工具基于 wasm-bindgen 与 web-sys 打造 Canvas 画板:Paint 示例全解析
基于 wasm bindgen 与 web sys 打造 Canvas 画板:Paint 示例全解析 Paint 是 wasm bindgen 仓库中一个典型的
开发工具在浏览器中为 Rust 代码计时:wasm-bindgen 的 web-sys `performance.now` 实战示例
在浏览器中为 Rust 代码计时:wasm bindgen 的 web sys performance.now 实战示例 导读 本文以 wasm bindgen
开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考