如何在React專案中直接使用WebAssembly
自從入坑WebAssembly以來,躺了很多坑,也瀏覽了很多資料,都沒有看到很多能夠直接在前端專案中使用WebAssembly的例子。即使有,我自己按照介紹的步驟一步一步來, 也會報各種錯誤,官方的文件也寫的比較模糊。於是,就決定自己擼一個,讓React專案能夠直接的藉助Webpack,在程式碼中引入已經編譯好的C++模組。
寫一個C語言模組
int add(int a, int b) { return a + b; } 複製程式碼
使用emscripten對C模組進行編譯
執行以下程式碼對上面的add.c
檔案進行編譯。
emcc add.c -Os -s WASM=1 -s SIDE_MODULE=1 -o add.wasm 複製程式碼
-Os
程式碼我的模組需要優化,-s WASM=1
代表我需要Wasm的第一個版本,-s SIDE_MODULE=1
代表我不需要多餘的程式碼,就只要這一個模組。-o add.wasm
表示我的輸出檔案為add.wasm
。然後就可以看到在與add.c
同級的目錄下生成了add.wasm
。然後把add.wasm
放到public
目錄下。
新建一個react專案
npx create-react-app my-project cd my-project yarn install yarn start 複製程式碼
執行完上述的命令,一個簡單的react專案就在你本地的3000埠啟動了。
獲取webpack控制權
然後再執行以下命令。
yarn run eject 複製程式碼
執行之後就可以看到webpack的配置檔案了。
安裝loader和fetch
yarn add wasm-loader && yarn add node-fetch 複製程式碼
更新webpack配置檔案
找到webpack配置檔案,在相應的位置新增如下配置。
{ test: /\.wasm$/, type: 'javascript/auto', loaders: ['wasm-loader'] } 複製程式碼
修改App.js檔案
修改App.js。將其替換為如下程式碼。
import React, {Component} from 'react'; import logo from './logo.svg'; import fetch from 'node-fetch'; import './App.css'; class App extends Component { componentDidMount() { this.doSomething(); } getExportFunction = async (url) => { const env = { memoryBase: 0, tableBase: 0, memory: new WebAssembly.Memory({ initial: 256 }), table: new WebAssembly.Table({ initial: 2, element: 'anyfunc' }) }; const instance = await fetch(url).then((response) => { return response.arrayBuffer(); }).then((bytes) => { return WebAssembly.instantiate(bytes, {env: env}) }).then((instance) => { return instance.instance.exports; }); return instance; }; doSomething = async () => { const wasmUrl = 'http://localhost:3000/add.wasm'; const { add } = await this.getExportFunction(wasmUrl); console.log(add(200,2034)); }; render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo"/> <p> Edit <code>src/App.js</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; 複製程式碼
可以看到App類中有個函式叫getExportFunction
,這個函式接受一個url
引數,這個url是遠端wasm檔案的地址。然後動態的根據傳入url,解析其中的編譯好的function
。