在浏览器上运行一个Hello Rust

26,680 阅读3分钟

deno1.0发布以来,rust这门语言开始进入不少前端开发者的视线,不过对于大部分前端开发者来说,rust这门语言还是很陌生的,至少我这个只会写一些业务的前端码农在尝试阅读一些deno源码的时候,基本处于看不懂的状态,于是在尝试了解rust这门语言的时候,发现了这样一个rust和js互相调用的库wasm-bindgen,看一下官方提供的示例

也就是说我们可以写一些rust的函数,在经过wasm-bindgen这个库编译之后,可以在js文件中调用rust写的函数了,感觉还是很有意思的,一下子前端二次元的壁垒被打通了的感觉。

花了一点时间研究了一下rust语言的安装以来以后,我也在浏览器端成功实现了一个rust版本的“Hello World”,下面就来介绍一下如何运行起这个Hello Rust函数。

安装rust语言相关依赖

第一步肯定要安装rust语言环境,对于rust语言的环境,需要安装rustc(rust语言的编译器),cargo(rust包管理工具),这俩个的安装大家可以自行百度

新建一个rust工程项目

使用cargo new 命令可以新建一个rust项目,我们看一下cargo新建的项目一半会包含一个src文件夹和一个Cargo.toml,类似于npm init中的package.json,我们可以在Cargo.toml中引入我们的wasm-bindgen


[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2.63"

然后在src的lib.rs中写入示例代码

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
    fn alert(s: &str);
} // 声明一个alert函数

#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hello, {}!", name));
} // greet函数传入name作为参数

然后执行cargo build命令可以构建cargo这个包,构建完以后,我们会发现项目多出一个pkg的文件夹,里面是编译出的js文件,其中重要的一个函数就是export 出之前的greet函数

```
export function greet(name) {
    var ptr0 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
    var len0 = WASM_VECTOR_LEN;
    wasm.greet(ptr0, len0);
}
```

于是我们就可以写一个index.js文件来调取pkg这个目录下的js文件

    const rust = import('./pkg');

    rust
      .then(m=>m.greet('Rust'))
      .catch(console.error);

配置webpack

最后我们是要在浏览器中打开这个alert函数,于是我们还需要配置一下webpack,npm init之后,package.json所需要安装的依赖

{
  "scripts": {
    "build": "webpack",
    "serve": "webpack-dev-server"
  },
  "devDependencies": {
    "@wasm-tool/wasm-pack-plugin": "1.0.1",
    "text-encoding": "^0.7.0",
    "html-webpack-plugin": "^3.2.0",
    "webpack": "^4.29.4",
    "webpack-cli": "^3.1.1",
    "webpack-dev-server": "^3.1.0"
  }
}

至于wasm-pack这个插件,大家想要了解的可以自行去百度了解一下,是一个构建WebAssembly包的工具。

最后配置我们的webpack.config.json

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin");

module.exports = {
    entry: './index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'index.js',
    },
    plugins: [
        new HtmlWebpackPlugin(),
        new WasmPackPlugin({
            crateDirectory: path.resolve(__dirname, ".")
        }),
        // Have this example work in Edge which doesn't ship `TextEncoder` or
        // `TextDecoder` at this time.
        new webpack.ProvidePlugin({
          TextDecoder: ['text-encoding', 'TextDecoder'],
          TextEncoder: ['text-encoding', 'TextEncoder']
        })
    ],
    mode: 'development'
};

执行npm run serve就可以在浏览器端跑起来一个rust写的Hello World函数啦