相关文章推荐
很拉风的罐头  ·  vscode git blame - CSDN文库·  1 周前    · 
体贴的李子  ·  Matlab - ...·  1 年前    · 
绅士的围巾  ·  cv2 imencode jpg ...·  1 年前    · 
机灵的鸡蛋面  ·  javascript - Read ...·  1 年前    · 

rust-wasm + react 新手入门

本文未经许可,禁止任何形式的转载!!!

发现必究!!!

所有文章第一时间发布在公众号:超级英雄吉姆。

这篇文章花了很多心血。希望能够帮助到大家,同时也希望大家能够点赞、关注,这是我持续写作的最大动力!


概要

为什么需要 Webassembly?

曾经复杂计算的需求,多数聚集在后端,随着的技术和业务的日益发展,在前端也出现了越来越多的频繁复杂计算和高性能的需求。此时通过 js 来和后端交互,反而优秀的 js 变成了应用的瓶颈

在这样的情况下,WebAssembly(WASM)提供了高性能和安全的环境,以接近本机的速度来运行计算。

WASM 是一种编译目标,而不是一种语言,你可以通过各种语言(Rust、Golang、C、C++...)编译得到。Chrome、FireFox、Safari、Edge 中得到了很好的支持。

准备

相关知识:

react node npm wasm-pack

rust rust-wasm cargo cargo-generate wasm-bindgen

linux linux常用命令

如果你对 Rust React 没有相关的知识储备,请先参照官方文档。

环境准备:

注: 教程的环境为 mac 系统。

我们需要 npm cargo 。用来构建 react 应用和 rust-wasm。

如果你对两者没有了解。请先参照官方教程。

步骤概览

  • 创建 React 应用
  • Eject React 应用
  • cargo new 创建 Rust 应用
  • 创建 Rust 应用
  • 编译 WASM
  • 在 React 应用中使用 WASM
  • 附加 使用 cargo-generate 创建 Rust-Wasm 应用

创建 React 应用

如果你已经使用 React 脚手架,那么你应该会有 npx 命令,这里创建的 React 应用的方式和 React 官方文档一致。就不赘述。

  • 创建目录 mkdir react-wasm
  • 进入目录 cd react-wasm
  • 创建应用 npx create-react-app react-client

当创建好以后我们得到目录结构如下

➜  react-client git:(master) ls
README.md         node_modules      package-lock.json package.json      public            src
  • 弹出配置(Ejecting)

参考资料: stackoverflow.com/quest

  • 运行命令 npm run eject

命令完成后,结构如下:

➜  react-client git:(master) ✗ ls
README.md         config            node_modules      package-lock.json package.json      public            scripts           src

测试一下 React 应用是否正常

  • react-client 目录下运行 npm start

浏览器中访问 http://localhost:3000/ ,看到以下的结果,证明 React 应用正常。

创建 Rust 应用

回到 react-wasm 目录下。

➜  react-wasm ls
react-client
  • 我们使用 cargo 来创建一个新的文件夹
  • 运行 cargo new wasm ,结果如下
➜  react-wasm ls
react-client wasm
  • 进入到 wasm 目录下
➜  wasm git:(master) ✗ ls
Cargo.lock  Cargo.toml  src  target
  • 打开 Cargo.toml
[package]
name = "wasm"
version = "0.1.0"
authors = ["jim <303600370@qq.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
  • 增加依赖
[package]
name = "wasm"
version = "0.1.0"
authors = ["jim <303600370@qq.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib"]
path ="src/lib.rs"
[dependencies]
wasm-bindgen ="0.2.34"
  • 进入到 src 目录下 将 main.rs 重命名或者删除之后创建 lib.rs
➜  wasm git:(master) ✗ ls
Cargo.lock Cargo.toml src        target
➜  wasm git:(master) ✗ cd src
➜  src git:(master) ✗ ls
main.rs
➜  src git:(master) ✗ mv main.rs lib.rs
➜  src git:(master) ✗ ls
lib.rs
➜  src git:(master) ✗
  • 运行 cargo build 看下是否能正常编译
➜  src git:(master) ✗ cargo build
   Compiling proc-macro2 v1.0.24
   Compiling log v0.4.14
   Compiling wasm-bindgen-shared v0.2.71
   Compiling syn v1.0.60
   Compiling bumpalo v3.6.1
   Compiling quote v1.0.9
   Compiling wasm-bindgen-backend v0.2.71
   Compiling wasm-bindgen-macro-support v0.2.71
   Compiling wasm-bindgen-macro v0.2.71
   Compiling wasm-bindgen v0.2.71
   Compiling wasm v0.1.0 (/Users/jim/dev/tmp/react-wasm/wasm)
    Finished dev [unoptimized + debuginfo] target(s) in 11.70s
  • 编辑 lib.rs 内容
use::wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
    fn alert(s: &str);
#[wasm_bindgen]
pub fn hello() {
    unsafe {
        alert("Hello World");

#[wasm_bindgen] 会告诉 wasm-bindgen 帮我们生成一个可以调用的方法

此时,你已经准备好了编译 wasm 文件并在 react 应用中使用

关于 wasm-bindgen

  • 将 JS 功能导入到 Rust 中,例如 DOM 操作, 控制台日志记录或性能监控。
  • 将 Rust 功能导出到 JS,例如类,函数等
  • 使用丰富的类型,例如字符串,数字,类,闭包和对象,而不是简单地使用 u32 浮点数。
  • 自动为 JS 使用的 Rust 代码生成 TypeScript 绑定

可以参照官方文档 : rustwasm.github.io/docs

编译 WASM

我们已经完成了定义 Rust 函数并告诉 wasm-bindgen 编译内容的工作。wasm-pack 帮助我们创建 Javascript 和 Typescript 接口。

  • 使用 cargo 安装 wasm-pack
  • 运行 cargo install wasm-pack 命令

由于本机环境已经安装过,所以得到以下结果

➜  src git:(master) ✗ cargo install wasm-pack
    Updating `git://mirrors.ustc.edu.cn/crates.io-index` index
  Downloaded wasm-pack v0.9.1 (registry `git://mirrors.ustc.edu.cn/crates.io-index`)
  Downloaded 1 crate (422.5 KB) in 3.23s
     Ignored package `wasm-pack v0.9.1` is already installed, use --force to override
➜  src git:(master) ✗

同样可以参考官方文档

wasm-pack : rustwasm.github.io/wasm

  • 确保你的 wasm-pack 已经安装完成
  • 运行 wasm-pack 命令,得到以下结果
➜  src git:(master) ✗ wasm-pack
wasm-pack 0.9.1
Ashley Williams <ashley666ashley@gmail.com>
  ✨  pack and publish your wasm!
USAGE:
    wasm-pack [FLAGS] [OPTIONS] <SUBCOMMAND>
FLAGS:
    -h, --help       Prints help information
    -q, --quiet      No output printed to stdout
    -V, --version    Prints version information
    -v, --verbose    Log verbosity is based off the number of v used
OPTIONS:
        --log-level <log_level>    The maximum level of messages that should be logged by wasm-pack. [possible values:
                                   info, warn, error] [default: info]
SUBCOMMANDS:
    build       ️  build your npm package!
    help       Prints this message or the help of the given subcommand(s)
    login         Add an npm registry user account! (aliases: adduser, add-user)
    new          create a new project with a template
    pack          create a tar of your npm package but don't publish!
    publish       pack up your npm package and publish!
    test        ‍   test your wasm!
  • 使用 wasm-pack build 命令编译 wasm 文件
  • 可以通过 --out-dir 来指定文件输出位置
  • 这里我们不指定目录直接运行 wasm-pack build 命令
➜  src git:(master) ✗ wasm-pack build
[INFO]:    Checking for the Wasm target...
[INFO]:    Compiling to Wasm...
   Compiling proc-macro2 v1.0.24
   Compiling unicode-xid v0.2.1
   Compiling log v0.4.14
   Compiling syn v1.0.60
   Compiling wasm-bindgen-shared v0.2.71
   Compiling cfg-if v1.0.0
   Compiling bumpalo v3.6.1
   Compiling lazy_static v1.4.0
   Compiling wasm-bindgen v0.2.71
   Compiling quote v1.0.9
   Compiling wasm-bindgen-backend v0.2.71
   Compiling wasm-bindgen-macro-support v0.2.71
   Compiling wasm-bindgen-macro v0.2.71
   Compiling wasm v0.1.0 (/Users/jim/dev/tmp/react-wasm/wasm)
warning: unnecessary `unsafe` block
  --> src/lib.rs:13:5
13 |     unsafe {
   |     ^^^^^^ unnecessary `unsafe` block
   = note: &#x60;#[warn(unused_unsafe)]` on by default
warning: 1 warning emitted
    Finished release [optimized] target(s) in 10.75s
⚠️   [WARN]: origin crate has no README
[INFO]: ⬇️  Installing wasm-bindgen...
[INFO]: Optimizing wasm binaries with `wasm-opt`...
[INFO]: Optional fields missing from Cargo.toml: 'description', 'repository', and 'license'. These are not necessary, but recommended
[INFO]: ✨   Done in 6m 50s
[INFO]:     Your wasm pkg is ready to publish at /Users/jim/dev/tmp/react-wasm/wasm/pkg.
  • wasm 目录下生成了一个 pkg 目录
➜  wasm git:(master) ✗ ls
Cargo.lock Cargo.toml pkg        src        target
➜  wasm git:(master) ✗ cd pkg
➜  pkg git:(master) ✗ ls
package.json      wasm.d.ts         wasm.js           wasm_bg.js        wasm_bg.wasm      wasm_bg.wasm.d.ts
➜  pkg git:(master) ✗

pkg 目录中 *.wasm 就是我们的 WASM 文件。其中还包括了 typescript 的定义 *.d.ts 和 js 文件 *.js 。另外,它还会生成一个 package.json ,接下来,我们将会使用这个文件配合 npm 成为我们 react 的应用依赖。

在 React 应用中使用 WASM

回到我们的 React 应用

  • 打开 /react-client/package.json
{
  "name": "react-client",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@babel/core": "7.12.3",
    "@pmmmwh/react-refresh-webpack-plugin": "0.4.3",
    "@svgr/webpack": "5.5.0",
    "@testing-library/jest-dom": "^5.11.9",
    "@testing-library/react": "^11.2.5",
    "@testing-library/user-event": "^12.8.1",
    "@typescript-eslint/eslint-plugin": "^4.5.0",
    "@typescript-eslint/parser": "^4.5.0",
    "babel-eslint": "^10.1.0",
    "babel-jest": "^26.6.0",
    "babel-loader": "8.1.0",
    "babel-plugin-named-asset-import": "^0.3.7",
    "babel-preset-react-app": "^10.0.0",
    "bfj": "^7.0.2",
    "camelcase": "^6.1.0",
    "case-sensitive-paths-webpack-plugin": "2.3.0",
    "css-loader": "4.3.0",
    "dotenv": "8.2.0",
    "dotenv-expand": "5.1.0",
    "eslint": "^7.11.0",
    "eslint-config-react-app": "^6.0.0",
    "eslint-plugin-flowtype": "^5.2.0",
    "eslint-plugin-import": "^2.22.1",
    "eslint-plugin-jest": "^24.1.0",
    "eslint-plugin-jsx-a11y": "^6.3.1",
    "eslint-plugin-react": "^7.21.5",
    "eslint-plugin-react-hooks": "^4.2.0",
    "eslint-plugin-testing-library": "^3.9.2",
    "eslint-webpack-plugin": "^2.5.2",
    "file-loader": "6.1.1",
    "fs-extra": "^9.0.1",
    "html-webpack-plugin": "4.5.0",
    "identity-obj-proxy": "3.0.0",
    "jest": "26.6.0",
    "jest-circus": "26.6.0",
    "jest-resolve": "26.6.0",
    "jest-watch-typeahead": "0.6.1",
    "mini-css-extract-plugin": "0.11.3",
    "optimize-css-assets-webpack-plugin": "5.0.4",
    "pnp-webpack-plugin": "1.6.4",
    "postcss-flexbugs-fixes": "4.2.1",
    "postcss-loader": "3.0.0",
    "postcss-normalize": "8.0.1",
    "postcss-preset-env": "6.7.0",
    "postcss-safe-parser": "5.0.2",
    "prompts": "2.4.0",
    "react": "^17.0.1",
    "react-app-polyfill": "^2.0.0",
    "react-dev-utils": "^11.0.3",
    "react-dom": "^17.0.1",
    "react-refresh": "^0.8.3",
    "resolve": "1.18.1",
    "resolve-url-loader": "^3.1.2",
    "sass-loader": "^10.0.5",
    "semver": "7.3.2",
    "style-loader": "1.3.0",
    "terser-webpack-plugin": "4.2.3",
    "ts-pnp": "1.2.0",
    "url-loader": "4.1.1",
    "web-vitals": "^1.1.0",
    "webpack": "4.44.2",
    "webpack-dev-server": "3.11.1",
    "webpack-manifest-plugin": "2.2.0",
    "workbox-webpack-plugin": "5.1.4"
  "scripts": {
    "start": "node scripts/start.js",
    "build": "node scripts/build.js",
    "test": "node scripts/test.js"
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
  "jest": {
    "roots": [
      "<rootDir>/src"
    "collectCoverageFrom": [
      "src/**/*.{js,jsx,ts,tsx}",
      "!src/**/*.d.ts"
    "setupFiles": [
      "react-app-polyfill/jsdom"
    "setupFilesAfterEnv": [
      "<rootDir>/src/setupTests.js"
    "testMatch": [
      "<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}",
      "<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}"
    "testEnvironment": "jsdom",
    "testRunner": "/Users/jim/dev/tmp/react-wasm/react-client/node_modules/jest-circus/runner.js",
    "transform": {
      "^.+\\.(js|jsx|mjs|cjs|ts|tsx)$": "<rootDir>/config/jest/babelTransform.js",
      "^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
      "^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
    "transformIgnorePatterns": [
      "[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$",
      "^.+\\.module\\.(css|sass|scss)$"
    "modulePaths": [],
    "moduleNameMapper": {
      "^react-native$": "react-native-web",
      "^.+\\.module\\.(css|sass|scss)$": "identity-obj-proxy"
    "moduleFileExtensions": [
      "web.js",
      "js",
      "web.ts",
      "ts",
      "web.tsx",
      "tsx",
      "json",
      "web.jsx",
      "jsx",
      "node"
    "watchPlugins": [
      "jest-watch-typeahead/filename",
      "jest-watch-typeahead/testname"
    "resetMocks": true
  "babel": {
    "presets": [
      "react-app"
  • dependencies 中增加依赖项
    "wasm":"file:../wasm/pkg"

结果如下

{
  "name": "react-client",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@babel/core": "7.12.3",
    "@pmmmwh/react-refresh-webpack-plugin": "0.4.3",
    "@svgr/webpack": "5.5.0",
    "@testing-library/jest-dom": "^5.11.9",
    "@testing-library/react": "^11.2.5",
    "@testing-library/user-event": "^12.8.1",
    "@typescript-eslint/eslint-plugin": "^4.5.0",
    "@typescript-eslint/parser": "^4.5.0",
    "babel-eslint": "^10.1.0",
    "babel-jest": "^26.6.0",
    "babel-loader": "8.1.0",
    "babel-plugin-named-asset-import": "^0.3.7",
    "babel-preset-react-app": "^10.0.0",
    "bfj": "^7.0.2",
    "camelcase": "^6.1.0",
    "case-sensitive-paths-webpack-plugin": "2.3.0",
    "css-loader": "4.3.0",
    "dotenv": "8.2.0",
    "dotenv-expand": "5.1.0",
    "eslint": "^7.11.0",
    "eslint-config-react-app": "^6.0.0",
    "eslint-plugin-flowtype": "^5.2.0",
    "eslint-plugin-import": "^2.22.1",
    "eslint-plugin-jest": "^24.1.0",
    "eslint-plugin-jsx-a11y": "^6.3.1",
    "eslint-plugin-react": "^7.21.5",
    "eslint-plugin-react-hooks": "^4.2.0",
    "eslint-plugin-testing-library": "^3.9.2",
    "eslint-webpack-plugin": "^2.5.2",
    "file-loader": "6.1.1",
    "fs-extra": "^9.0.1",
    "html-webpack-plugin": "4.5.0",
    "identity-obj-proxy": "3.0.0",
    "jest": "26.6.0",
    "jest-circus": "26.6.0",
    "jest-resolve": "26.6.0",
    "jest-watch-typeahead": "0.6.1",
    "mini-css-extract-plugin": "0.11.3",
    "optimize-css-assets-webpack-plugin": "5.0.4",
    "pnp-webpack-plugin": "1.6.4",
    "postcss-flexbugs-fixes": "4.2.1",
    "postcss-loader": "3.0.0",
    "postcss-normalize": "8.0.1",
    "postcss-preset-env": "6.7.0",
    "postcss-safe-parser": "5.0.2",
    "prompts": "2.4.0",
    "react": "^17.0.1",
    "react-app-polyfill": "^2.0.0",
    "react-dev-utils": "^11.0.3",
    "react-dom": "^17.0.1",
    "react-refresh": "^0.8.3",
    "resolve": "1.18.1",
    "resolve-url-loader": "^3.1.2",
    "sass-loader": "^10.0.5",
    "semver": "7.3.2",
    "style-loader": "1.3.0",
    "terser-webpack-plugin": "4.2.3",
    "ts-pnp": "1.2.0",
    "url-loader": "4.1.1",
    "web-vitals": "^1.1.0",
    "webpack": "4.44.2",
    "webpack-dev-server": "3.11.1",
    "webpack-manifest-plugin": "2.2.0",
    "workbox-webpack-plugin": "5.1.4",
    "wasm":"file:../wasm/pkg"
  "scripts": {
    "start": "node scripts/start.js",
    "build": "node scripts/build.js",
    "test": "node scripts/test.js"
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
  "jest": {
    "roots": [
      "<rootDir>/src"
    "collectCoverageFrom": [
      "src/**/*.{js,jsx,ts,tsx}",
      "!src/**/*.d.ts"
    "setupFiles": [
      "react-app-polyfill/jsdom"
    "setupFilesAfterEnv": [
      "<rootDir>/src/setupTests.js"
    "testMatch": [
      "<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}",
      "<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}"
    "testEnvironment": "jsdom",
    "testRunner": "/Users/jim/dev/tmp/react-wasm/react-client/node_modules/jest-circus/runner.js",
    "transform": {
      "^.+\\.(js|jsx|mjs|cjs|ts|tsx)$": "<rootDir>/config/jest/babelTransform.js",
      "^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
      "^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
    "transformIgnorePatterns": [
      "[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$",
      "^.+\\.module\\.(css|sass|scss)$"
    "modulePaths": [],
    "moduleNameMapper": {
      "^react-native$": "react-native-web",
      "^.+\\.module\\.(css|sass|scss)$": "identity-obj-proxy"
    "moduleFileExtensions": [
      "web.js",
      "js",
      "web.ts",
      "ts",
      "web.tsx",
      "tsx",
      "json",
      "web.jsx",
      "jsx",
      "node"
    "watchPlugins": [
      "jest-watch-typeahead/filename",
      "jest-watch-typeahead/testname"
    "resetMocks": true
  "babel": {
    "presets": [
      "react-app"
  • 如果你要更改依赖的名称你需要回到 wasm/pkg 下编辑 package.json
{
  "name": "wasm",
  "collaborators": [
    "jim <303600370@qq.com>"
  "version": "0.1.0",
  "files": [
    "wasm_bg.wasm",
    "wasm.js",
    "wasm.d.ts"
  "module": "wasm.js",
  "types": "wasm.d.ts",
  "sideEffects": false
  • 安装 wasm-loader
  • react-client 目录下运行 npm install --save-dev wasm-loader ,结果如下
➜  react-client git:(master) ✗ npm install --save-dev wasm-loader
npm WARN tsutils@3.20.0 requires a peer of typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta but none is installed. You must install peer dependencies yourself.
+ wasm-loader@1.3.0
added 8 packages from 11 contributors and audited 1962 packages in 12.833s
132 packages are looking for funding
  run `npm fund` for details
found 0 vulnerabilities
  • 打开 react-client/config 目录下的 webpack.config.js 文件,在 rules 中添加以下内容:
   //如果存在这行,则不需要
   { parser: { requireEnsure: false } },
      test: /\.wasm$/, // only load WASM files (ending in .wasm)
      // only files in our src/ folder
      include: path.resolve(__dirname, "src"),
      use: [{
         // load and use the wasm-loader dictionary
         loader: require.resolve("wasm-loader"),
         options: {}
  • 找到 file-loader ,如下:
            {
              loader: require.resolve('file-loader'),
              // Exclude `js` files to keep "css" loader working as it injects
              // its runtime that would otherwise be processed through "file" loader.
              // Also exclude `html` and `json` extensions so they get processed
              // by webpacks internal loaders.
              exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
              options: {
                name: 'static/media/[name].[hash:8].[ext]',
  • file-loader 中添加 /\.wasm$/
            {
              loader: require.resolve('file-loader'),
              // Exclude `js` files to keep "css" loader working as it injects
              // its runtime that would otherwise be processed through "file" loader.
              // Also exclude `html` and `json` extensions so they get processed
              // by webpacks internal loaders.
              exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/,/\.wasm$/],
              options: {
                name: 'static/media/[name].[hash:8].[ext]',

恭喜你到了这一步,接下来我们要修改 App.js 里的内容。

  • 打开 /react-client/src 中的 App.js
import logo from './logo.svg';
import './App.css';
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
          Edit <code>src/App.js</code> and save to reload.
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
          Learn React
      </header>
export default App;
  • 修改 App.js ,添加 import('wasm').then(module => { console.log(module) })
import logo from './logo.svg';
import './App.css';
function App() {
  import('wasm').then(module => {
    console.log(module)
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
          Edit <code>src/App.js</code> and save to reload.
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
          Learn React
      </header>
export default App;
  • 运行 npm i 保证我们的依赖和配置生效
➜  src git:(master) ✗ npm i
npm WARN tsutils@3.20.0 requires a peer of typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta but none is installed. You must install peer dependencies yourself.
audited 1963 packages in 7.57s
132 packages are looking for funding
  run `npm fund` for details
found 0 vulnerabilities
  • 启动 react 应用。打开控制台,看一下输出

可以看到 wasm 已经已经应用成功,还可以看到我们在 rust 应用中定义的 hello 方法

  • 编辑 App.js ,调用我们的 wasm 中的 hello 方法
import logo from './logo.svg';
import './App.css';
function App() {
  import('wasm').then(({hello}) => {
    hello();
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
          Edit <code>src/App.js</code> and save to reload.
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
          Learn React
      </header>
export default App;

*恭喜你~~~~!!!,我们成功的调用了在 rust 应用中定义的 hello 方法,并把它集成在 react 应用中了 *

附加:使用 cargo-generate 创建 Rust-Wasm 应用

如果你阅读到此处还是不能够理解整个流程中我们做了什么的话,建议你重新阅读或者思考一下整个流程。

接下来的内容会需要你对以上内容有一定理解之后阅读起来会比较轻松。接下来的内容,是在上文中的扩展。

  1. 安装 cargo-generate
cargo install cargo-generate

如果没有 openssl 则使用

cargo install cargo-generate --features vendored-openssl

用例: cargo generate --git https://github.com/githubusername/mytemplate.git

  1. 安装 wasm-pack
cargo install wasm-pack
  1. 安装 wasm-bindgen
cargo install wasm-bindgen-cli --force
  1. 生成 rust 应用
cargo generate --git https://github.com/rustwasm/wasm-pack-template.git --name my-project
cd my-project

得到结果如下

➜  react-wasm cargo generate --git https://github.com/rustwasm/wasm-pack-template.git --name my-project
cd my-project
    Creating project called `my-project`...
✨   Done! New project created /Users/jim/dev/tmp/react-wasm/my-project
➜  my-project git:(master) ✗

目录结构

➜  my-project git:(master) ✗ ls