React项目中直接使用WebAssembly

2018-11-0308:50:38WEB前端开发Comments6,815 views字数 2019阅读模式

入坑WebAssembly以来,躺了很多坑,也浏览了很多资料,都没有看到很多能够直接在前端项目中使用WebAssembly的例子。即使有,我自己按照介绍的步骤一步一步来, 也会报各种错误,官方的文档也写的比较模糊。于是,就决定自己撸一个,让React项目能够直接的借助Webpack,在代码中引入已经编译好的C++模块。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/7638.html

写一个C语言模块

int add(int a, int b) {
  return a + b;
}
复制代码

使用emscripten对C模块进行编译

执行以下代码对上面的add.c文件进行编译。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/7638.html

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目录下。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/7638.html

新建一个react项目

npx create-react-app my-project
cd my-project
yarn install
yarn start
复制代码

执行完上述的命令,一个简单的react项目就在你本地的3000端口启动了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/7638.html

获取webpack控制权

然后再执行以下命令。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/7638.html

yarn run eject
复制代码

运行之后就可以看到webpack的配置文件了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/7638.html

安装loader和fetch

yarn add wasm-loader && yarn add node-fetch
复制代码

更新webpack配置文件

找到webpack配置文件,在相应的位置添加如下配置。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/7638.html

{
    test: /\.wasm$/,
    type: 'javascript/auto',
    loaders: ['wasm-loader']
}
复制代码

修改App.js文件

修改App.js。将其替换为如下代码。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/7638.html

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文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/7638.html

运行

执行以下命令启动项目。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/7638.html

yarn start
复制代码

然后就可以在控制台中看到输出的49,是直接调用的我们用C语言写的add函数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/7638.html

举个例子

完整的项目代码在这里,欢迎Star。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/7638.html

作者:detectiveHLH
来源:掘金文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/7638.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/gcs/7638.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定