WebAssembly增强前端应用技巧详解

目录
  • 准备
  • 开始
    • 创建项目
    • 打包 wasm
    • 前端调用
    • 使用 console.log
  • 总结

准备

此篇文章我们主要使用 Rust 来编写我们的 WebAssembly 工具库然后在 React 应用进行使用。所以需要准备好下列的环境

  • Rust 开发环境(rustup、rustc、cargo 这些)
  • 前端开发环境(node、npm 这些)
  • wasm-pack (cargo install wasm-pack)

开始

开始前我们先要准备一个前端应用,这里我们使用 create-react-app 来创建一个 React 项目。 如果没有安装 create-react-app ,先用 pnpm (npm / yarn 也行)全局安装一下

npm install -g create-react-app

创建项目

使用 typescript 模板来创建项目,以获得更好的类型提示。

create-react-app react-wasm --template typescript

进入到刚创建好的项目目录中

cd react-wasm

创建好 react 项目之后,我们接下来使用 wasm-pack 创建一个 wasm 工具库

wasm-pack new wasm-lib

创建完成后我们的目录结构是像下面这样子的,

src 目录主要编写前端应用代码

wasm-lib/src 目录主要编写 rust wasm 代码

wasm-lib/src/lib.rs 目录下,这里就是我们可以进行编写供前端调用的 WebAssembly 函数。这里默认写好了一个 greet 函数,然后里面调用了 alert 弹框。接下来我们就去看看如何在前端中进行使用这个函数。

mod utils;
use wasm_bindgen::prelude::*;
// 当 `wee_alloc` 特性开启的时候, 使用 `wee_alloc` 作为全局分配器
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
extern "C" {
    fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet() {
    alert("Hello, wasm-lib!");
}

打包 wasm

在 package.json 文件中添加这一行代码,然后我们就可以进行打包了。

项目根目录中运行

npm run build:wasm

如果在 build 的过程卡住了,或者报错了。可以先暂时把代码优化给关闭掉

在 wasm-lib 目录下的 Cargo.toml 配置文件中关掉 wasm-opt

打包完成后就能看到项目根目录中出现了一个 pkg 文件夹,这里面就是我们打包后的产物,前端可以进行调用我们用 Rust 编写的函数。

前端调用

我们有两种方式去调用 pkg 目录下的 wasm 函数:

一种是将 pkg 作为一个 npm 包发布

cd wasm-lib
# 该命令可以把这个库作为 npm 包发布到 npm 中,然后我们前端就正常的方式 npm install 就可以使用了
wasm-pack publish

另一种是先在本地进行引用,根目录下安装

npm install ./pkg

然后 package.json 的依赖中增加了我们的本地库:

{
  "name": "react-wasm",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/react": "^13.3.0",
    "@testing-library/user-event": "^13.5.0",
    "@types/jest": "^27.5.1",
    "@types/node": "^16.11.36",
    "@types/react": "^18.0.9",
    "@types/react-dom": "^18.0.5",
    "react": "^18.1.0",
    "react-dom": "^18.1.0",
    "react-scripts": "5.0.1",
    "typescript": "^4.7.2",
    "wasm-lib": "file:pkg", // ++++++++++++++++++++++++++++
    "web-vitals": "^2.1.4"
  },
  // ...
}

接下来就去我们的 App.tsx 中调用 greet 方法:

import React, { useEffect } from "react";
import init, { greet } from "wasm-lib";
import logo from "./logo.svg";
import "./App.css";
function App() {
  // +++++++++++++++++
  useEffect(() => {
    init().then(() => {
      greet();
    });
  }, []);
  return (
    <div className="App">
      ...
    </div>
  );
}
export default App;

然后开始运行我们的 react 应用

npm run start

打开 localhost:3000 端口,可以看到我们调用 alert 方法成功咯~

使用 console.log

首先我们要安装一下 web-sys 这个包,在 Cargo.toml 中加入

[dependencies]
wasm-bindgen = "0.2.63"
web-sys = { version = "0.3.57", features = ['console'] } # ++++++++

在这里我们开启了 console 这个 feature, web-sys 还支持很多 feature,比如可以操作 DOM,调用前端原生 fetch API , 操作 Canvas , WebGL 等等等。

Rust:

mod utils;
use web_sys::console;
use wasm_bindgen::prelude::*;
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
pub fn test_log(val: JsValue) {
    console::log_2(&"从JS端接受到数据".into(), &val);
}

JS:

import React, { useEffect } from "react";
import init, { test_log } from "wasm-lib";
import logo from "./logo.svg";
import "./App.css";
function App() {
  useEffect(() => {
    init().then(() => {
      test_log({ a: 1, b: 2, c: 3 });
    });
  }, []);
  return (
    <div className="App">
      ...
    </div>
  );
}
export default App;

打印结果:

总结

像一些复杂的计算,我们可以使用 WebAssembly 来进行操作,比如上一篇。 WebAssembly 目前论开发效率来说个人感觉是不如原生 JS 的,稍微有点繁琐,目前感觉它的应用场景更多是在复杂性的计算领域,比如写游戏、音视频解析、加密解密、图片解析等这种需要复杂计算的。这里只是提供一个基础的小demo,让大家对这个东西有一个感性的了解,更深入的东西就得后面用到的时候再去了解了。

最后这里放上 官方参考文档

以上就是WebAssembly增强前端应用技巧详解的详细内容,更多关于WebAssembly增强前端应用的资料请关注我们其它相关文章!

(0)

相关推荐

  • 深入了解JavaScript 的 WebAssembly

    JavaScript 的 WebAssembly 本周发布的 Firefox 52 加入了对 WebAssembly 的支持,成为第一个支持 WebAssembly 标准的浏览器,而其它浏览器如 Chrome 57.Safari 和 Edge 也都会陆续支持 WebAssembly.WebAssembly 源于Mozilla 发起的 Asm.js 项目,设计补充而非取代 JavaScript,它是一个二进制格式,容易翻译到原生代码,本地解码速度比 JS 解析快得多,让高性能的 Web 应用在浏览

  • JS如何调用WebAssembly编译出来的.wasm文件

    WebAssembly也叫浏览器字节码技术 这里就不过多的解释了网上很多介绍 主要是让大家知道在js里面如何调用执行它,我之前看WebAssemblyAPI时候反正是看得一脸懵逼 也是为了大家能更快的入手这个比较新的技术吧 这边写的一个dom是官方推荐的c/c++编译的 c代码 int add (int x, int y) { return x + y; } int square (int x) { return x * x; } 属性c但是对字节码不熟悉的朋友可能会不理解,为什么没有main函

  • Go语言对前端领域的入侵WebAssembly运行原理

    目录 引言 WebAssembly 运行原理 Go WebAssembly 运行原理 Go WebAssembly 初体验 第一步 第二步 第三步 第四步 第五步 Javascript 真的需要担心 Go WebAssembly 的威胁么? 引言 从 Go 语言诞生以来,它就开始不断侵蚀 Java .C.C++ 语言的领地.今年下半年 Go 语言发布了 1.11 版本,引入了 WebAssembly 技术,浏览器端 Javascript 的垄断地位也开始遭遇 Go 语言的攻击.这次不同以往,它意

  • Rust开发WebAssembly在Html和Vue中的应用小结(推荐)

    目录 我最大的感受 Rust在web上的应用 本文主题 应用工具:HBuilder.CLion 1.创建一个wasm 2.在Html中的应用 4.最近遇到的问题 最初是由Mozilla研究院的Graydon Hoare设计创造,然后在Dave Herman, Brendan Eich以及很多其他人的贡献下逐步完善的.Rust的设计者们通过在研发Servo网站浏览器布局引擎过程中积累的经验优化了Rust语言和Rust编译器. 我最大的感受 开始我是抵触它的,原因很简单,它太难学了!!!好害怕语法上

  • WebAssembly增强前端应用技巧详解

    目录 准备 开始 创建项目 打包 wasm 前端调用 使用 console.log 总结 准备 此篇文章我们主要使用 Rust 来编写我们的 WebAssembly 工具库然后在 React 应用进行使用.所以需要准备好下列的环境 Rust 开发环境(rustup.rustc.cargo 这些) 前端开发环境(node.npm 这些) wasm-pack (cargo install wasm-pack) 开始 开始前我们先要准备一个前端应用,这里我们使用 create-react-app 来创

  • myeclipse8.5优化技巧详解

    还在为自己的配置低而抛弃MyEclipse8.5?还在为那低下的速度而苦恼吗?下面我们看看myeclipse8.5优化技巧的具体方法. 取消自动validation validation有一堆,什么xml.jsp.jsf.js等等,我们没有必要全部都去自动校验一下,只是需要的时候才会手工校验一下! 取消方法: windows–>perferences–>myeclipse–>validation 除开Manual下面的复选框全部选中之外,其他全部不选 手工验证方法: 在要验证的文件上,单

  • php安全攻防利用文件上传漏洞与绕过技巧详解

    目录 前言 文件上传漏洞的一些场景 场景一:前端js代码白名单判断.jpg|.png|.gif后缀 场景二:后端PHP代码检查Content-type字段 场景三:代码黑名单判断.asp|.aspx|.php|.jsp后缀 场景四:代码扩大黑名单判断 绕过方式--htaccsess: 绕过方式--大小写绕过: 场景五:一些复合判断 空格.点绕过(windows) ::$DATA绕过(windows) 双写绕过 %00截断 %0a绕过 图片马绕过 二次渲染绕过 条件竞争 /.绕过 前言 文件上传漏

  • python神经网络学习数据增强及预处理示例详解

    目录 学习前言 处理长宽不同的图片 数据增强 1.在数据集内进行数据增强 2.在读取图片的时候数据增强 3.目标检测中的数据增强 学习前言 进行训练的话,如果直接用原图进行训练,也是可以的(就如我们最喜欢Mnist手写体),但是大部分图片长和宽不一样,直接resize的话容易出问题. 除去resize的问题外,有些时候数据不足该怎么办呢,当然要用到数据增强啦. 这篇文章就是记录我最近收集的一些数据预处理的方式 处理长宽不同的图片 对于很多分类.目标检测算法,输入的图片长宽是一样的,如224,22

  • Iptables防火墙四表五链概念及使用技巧详解

    目录 1.链的概念 2.Iptables五种链的概念 3.Iptables数据流向经过的表 4.Iptables防火墙四种表的概念 5.Iptables防火墙表与链之间的优先级概念 6.Iptables防火墙表和链之间的使用技巧 **问题1:** **问题2:** 结论: 7.Iptables防火墙几种动作 1.链的概念 在防火墙中,用户想要成功进入内网环境,就需要发送请求报文,请求报文要和防火墙设置的各种规则进行匹配和判断,最后执行相应的动作(放行或者拒绝),一个防火墙中通常针对不同的来源设置

  • Golang 内存管理简单技巧详解

    目录 引言 预先分配切片 结构中的顺序字段 使用 map[string]struct{} 而不是 map[string]bool 引言 除非您正在对服务进行原型设计,否则您可能会关心应用程序的内存使用情况.内存占用更小,基础设施成本降低,扩展变得更容易/延迟. 尽管 Go 以不消耗大量内存而闻名,但仍有一些方法可以进一步减少消耗.其中一些需要大量重构,但很多都很容易做到. 预先分配切片 数组是具有连续内存的相同类型的集合.数组类型定义指定长度和元素类型.数组的主要问题是它们的大小是固定的——它们

  • JavaScript 条件判断使用技巧详解

    目录 引言 避免直接使用字符串作为条件 使用 Object 不符合预期,提前 return 使用 Map 配合 Object Map 也可以存储函数 尽量避免三目表达式和 switch 引言 本文花费很短的时间来介绍一下在 JavaScript 中如何编写更简单的条件判断,帮助你编写更简洁的代码和可读性更高的代码. 假如我们有一个颜色值转换十六进制编码的函数. function convertToHex(color) { if (typeof color === 'string') { if (

  • Git操作规范之tag的使用技巧详解

    目录 常用分支 master develop release hotfix 使用 注意 tag规范 打tag场景 tag命名规范 版本类型说明 版本号设置规范 场景举例 新需求 修复bug 重大版本更新 特殊情况 常用分支 首先分享一下我们的分支规范,然后再介绍摸索出的打tag的规范. master master : 主分支 , 最终在master分支对外发布, 此分支只能从其他分支合并,不能再这个分支直接修改 另外所有在master分支的推送应该打标签做记录,方便追溯 例如release合并到

  • Kotlin 嵌套函数开发技巧详解

    目录 1.嵌套函数 2.@JvmOverloads快捷实现函数重载 3.延迟初始化lateinit var 4.@JvmField减少属性set和get方法的生成 1.嵌套函数 业务开发中,我们可能会遇到这样一个场景:一个函数只会被某一处多次调用,且不想让这个函数在该类的其他地方调用,这个时候就需要对这个函数的访问性进行进一步限制. private是无法满足的,这个时候我们就可以使用嵌套函数提供更好的封装: fun test1() { //被限制访问行的函数 fun test2(content:

  • vue3 name 属性的使用技巧详解

    目录 引言 使用步骤 引言 如果你在 vue3 开发中使用了 <script setup> 语法的话,对于组件的 name 属性,需要做一番额外的处理. 对于 vue@3.2.34 及以上版本,在使用 <script setup> 的单文件组件时,vue 会根据组件文件名,自动推导出 name 属性.也就是名为 MyComponent.vue 或 my-component.vue 的文件, name 属性为 MyComponent,而当你在组件内显示定义 name 属性时,会覆盖推

随机推荐