Open13
React×RustでWebAssemblyをしてみる
環境
node v18.16.1
npx 9.5.1
rustc 1.67.1
cargo 1.67.1
wasm-pack 0.12.1
プロジェクトを作成する
npx create-react-app react-wasm --template typescript
いつもの画面を見にいく
cd react-wasm
npm start
react-wasm
ディレクトリでRustのプロジェクトを作成
cargo new --lib wasm-lib
この時のディレクトリ構造は下記の通り
react-wasm
├── README.md
├── node_modules
├── package-lock.json
├── package.json
├── public
├── src
├── tsconfig.json
└── wasm-lib // Rustのコード
wasm-lib
内を書き換える
react-wasm/wasm-lib/src/lib.rs
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn add(left: i32, right: i32) -> i32 {
return left + right;
}
react-wasm/wasm-lib/Cargo.toml
[package]
name = "wasm-lib"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
wasm-lib
ディレクトリでRustプロジェクトをビルドします
wasm-pack build --target web
するとpkg
ディレクトリができます
reactプロジェクト内でRustのコードを呼び出せるようにpackage.json
を変更
package.json
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.5.2",
"@types/node": "^16.18.46",
"@types/react": "^18.2.21",
"@types/react-dom": "^18.2.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4",
+ "wasm-lib": "file:wasm-lib/pkg"
},
パッケージを読み込む
npm install
index.tsx
とApp.tsx
を書き換える
react-wasm/src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<App />
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
react-wasm/src/App.tsx
import React from 'react';
import logo from './logo.svg';
import './App.css';
import init, { add } from "wasm-lib"; // .rsの関数(add)をimport
function App() {
// 呼び出す
init().then(() => {
const sum: number = add(1, 2);
console.log(sum);
});
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
コンソールに出力された
ここまでのコード
ここまでの参考文献
今後の宿題
- wasm-packの詳細を理解する
- initをインポートした理由は?