WebAssembly入门

ByteRiderPro
• 阅读 4032

Wasm是什么?

MDN官方文档是这样给出定义

WebAssembly(为了书写方便,简称Wasm)是一种新的编码方式,可以在现代的网络浏览器中运行 - 它是一种低级的类汇编语言,具有紧凑的二进制格式,可以接近原生的性能运行,并为诸如C / C ++等语言提供一个编译目标,以便它们可以在Web上运行。它也被设计为可以与JavaScript共存,允许两者一起工作。

对于网络平台而言,WebAssembly具有巨大的意义——它提供了一条途径,以使得以各种语言编写的代码都可以以接近原生的速度在Web中运行。在这种情况下,以前无法以此方式运行的客户端软件都将可以运行在Web中。

WebAssembly被设计为可以和JavaScript一起协同工作——通过使用WebAssembly的JavaScript API,你可以把WebAssembly模块加载到一个JavaScript应用中并且在两者之间共享功能。这允许你在同一个应用中利用WebAssembly的性能和威力以及JavaScript的表达力和灵活性,即使你可能并不知道如何编写WebAssembly代码。


在学习于航老师的《WebAssembly入门课》开篇词中,老师是这样总结的“WebAssembly 是基于栈式虚拟机的虚拟二进制指令集(V-ISA),它被设计为高级编程语言的可移植编译目标”。

带着好奇心,开启我们的Wasm学习之路,创建属于自己的第一个Wasm应用。

环境安装

Rust

一门赋予每个人
构建可靠且高效软件能力的语言。
  • 安装
# macOS
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# 其他安装方式
# https://forge.rust-lang.org/infra/other-installation-methods.html
  • 命令
# 版本更新
rustup update

# 查看版本
cargo --version

# 构建项目
cargo build

# 运行项目
cargo run

# 测试项目
cargo test

# 为项目构建文档
cargo doc

# 将库发布到 crates.io
cargo publish
# nightly rust
rustup toolchain install nightly

rustup toolchain list

rustup override set nightly

Node.js

Node.js是基于Chrome的V8 JavaScript引擎构建的JavaScript运行时

wasm-pack

用于构建和使用您希望与JavaScript,浏览器或Node.js互操作的Rust生成的WebAssembly。
  • 安装
# macOS
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

# 其他安装方式
# https://rustwasm.github.io/wasm-pack/installer
  • 命令
# 创建
# https://rustwasm.github.io/docs/wasm-pack/commands/new.html
wasm-pack new <name> --template <template> --mode <normal|noinstall|force>

# 构建
# https://rustwasm.github.io/docs/wasm-pack/commands/build.html
wasm-pack build
  [--out-dir <out>]
  [--out-name <name>]
  [--<dev|profiling|release>]
  [--target <bundler|nodejs|web|no-modules>]
  [--scope <scope>]
  [mode <normal|no-install>]

# 测试
# https://rustwasm.github.io/docs/wasm-pack/commands/test.html
wasm-pack test

# 发包
# https://rustwasm.github.io/docs/wasm-pack/commands/pack-and-publish.html
# npm pack
wasm-pack pack
# npm publish
wasm-pack publish

Vite

下一代前端工具
# vite项目中安装
npm i -D vite-plugin-rsw
# or
yarn add -D vite-plugin-rsw

快速开始

  • 在原有vite项目中使用,只需安装配置vite-plugin-rsw插件即可。
  • 新项目可以使用vite提供的@vitejs/app初始化项目,然后安装配置vite-plugin-rsw
  • 新项目推荐使用我的脚手架create-xc-app,会定期更新维护相关版本依赖。

create-xc-app

⚡️在几秒钟内创建一个项目!维护了多种基于vite,deno等的前端项目模板。
npx create-xc-app my-wasm-app --template wasm-react

创建Wasm包

# 两种方式
# name如果以@开头创建npm组织包
# 会被转成中划线连接,需要手动修改文件夹名称
wasm-pack new <name>
# or
# name可以是npm组织
# 例:cargo new --lib @rsw/hello
# 需要手动配置Cargo.toml
cargo new --lib <name>

WebAssembly入门

项目结构

# 推荐目录结构
[my-wasm-app] # 项目根路径
|- [rust-crate] # npm包`rust-crate`
|    |- [pkg] # 生成wasm包的目录
|    |- [src] # rust源代码
|    | # 了解更多: https://doc.rust-lang.org/cargo/reference/cargo-targets.html
|    |- [target] # 项目依赖,类似于npm的`node_modules`
|    | # 了解更多: https://doc.rust-lang.org/cargo/reference/manifest.html
|    |- Cargo.toml # rust包管理清单
|    `- ...
|- [@rsw] # npm 组织包
|     |- [hello] # @rsw/hello, 目录结构同`rust-crate`
|     `- ...
|- [node_modules] # 前端的项目包依赖
|- [src] # 前端源代码(可以是vue, react, 或其他)
| # 了解更多: https://nodejs.dev/learn/the-package-json-guide
|- package.json # `npm`或`yarn`包管理清单
| # 了解更多: https://vitejs.dev/config
|- vite.config.ts # vite配置文件
| # 了解更多: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
|- tsconfig.json # vite配置文件
` ...

乍一看,可能会觉得目录有点复杂,其实它就是一个标准的基于vite前端项目,然后,在根路径下去添加我们需要构建的wasm包(一个rust crate会对应生成一个wasm包,可单独发布到npm上)

项目配置

Step1: vite.config.ts
// 以react项目为例
import reactRefresh from '@vitejs/plugin-react-refresh';
import { defineConfig } from 'vite';
import ViteRsw from 'vite-plugin-rsw';

export default defineConfig({
  plugins: [
    reactRefresh(),
    // 更多配置:https://github.com/lencx/vite-plugin-rsw
    ViteRsw({
      // 包含生产和开发模式
      mode: 'release',
      crates: [
        // 包名称,支持npm组织
        '@rsw/hello'
      ]
    }),
  ],
})
Step2: rust-crate/Cargo.toml
# ...

[lib]
# https://doc.rust-lang.org/reference/linkage.html
crate-type = ["cdylib"]
wasm-opt = false

# https://doc.rust-lang.org/cargo/reference/profiles.html
# dev | release | test | bench
[profile.release]
lto = true
opt-level = "s"

# https://doc.rust-lang.org/cargo/guide/dependencies.html
# 指定依赖项:https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html
# 依赖包及版本管理,与npm的`package.json`类似
[dependencies]
wasm-bindgen = "0.2.69"
Step3: rust-crate/src/lib.rs
use wasm_bindgen::prelude::*;

// Import the `window.alert` function from the Web.
#[wasm_bindgen]
extern "C" {
    fn alert(s: &str);
}

// Export a `greet` function from Rust to JavaScript, that alerts a hello message.
#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hello, {}!", name));
}
Step4: src/App.tsx
// src/App.tsx

import React, { useEffect } from 'react';
import init, { greet } from 'wasm-test';

import logo from './logo.svg';
import './App.css';

function App() {
  useEffect(() => {
    // wasm初始化,在调用`wasm-test`包方法时
    // 必须先保证已经进行过初始化,否则会报错
    // 如果存在多个wasm包,则必须对每一个wasm包进行初始化
    init();
  }, [])

  return (
    <div className="App">
      <header className="App-header">
        ![]({logo} className=)
        <p>Hello WebAssembly!</p>
        <p>Vite + Rust + React</p>
        <p>
          {/* 调用greet方法 */}
          <button onClick={() => greet('wasm')}>hi wasm</button>
        </p>
        <p>Edit <code>App.tsx</code> and save to test HMR updates.</p>
      </header>
    </div>
  )
}

export default App

WebAssembly入门

完整代码示例

源码: https://github.com/lencx/lear...

文章写到这里,整个wasm项目搭建已经完成,接下来就是大家发挥想象力的时候了。

相关链接

WebAssembly入门

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这