前言
自从入坑 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.
来源: https://juejin.im/post/5bd907e2f265da0ac962f16a