1. 程式人生 > >如何在React專案中直接使用WebAssembly

如何在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

執行

執行以下命令啟動專案。

yarn start
複製程式碼

然後就可以在控制檯中看到輸出的49,是直接呼叫的我們用C語言寫的add函式。

舉個例子

完整的專案程式碼在這裡,歡迎Star。