Hello Wasm

124 阅读2分钟

是什么

WebAssembly (简称 wasm) 是一种高效的、可移植的低级字节码格式,可以在现代浏览器中高性能运行。它由万维网联盟(W3C)标准化,是一种运行在 Web 平台上的二进制指令格式,旨在补充和扩展 JavaScript 的能力。

主要特点

  1. 高性能
    WebAssembly 是一种接近原生性能的运行时环境,适合高计算密集型任务,例如游戏、图像和视频处理、科学计算等。
  2. 跨平台和跨语言
    WebAssembly 可以由多种编程语言(如 C、C++、Rust、Go 等)编译生成。只要浏览器支持 WebAssembly,代码可以在任何设备上运行。
  3. 与 JavaScript 紧密集成
    WebAssembly 设计为与 JavaScript 协同工作。你可以从 JavaScript 调用 WebAssembly 模块,也可以让 WebAssembly 使用 JavaScript 的功能。
  4. 安全性
    WebAssembly 在沙盒环境中运行,并且遵守浏览器的安全模型,不会破坏用户设备。
  5. 快速加载
    WebAssembly 的二进制格式相比于传统的 JavaScript 更小且加载速度更快。

应用场景

  1. 游戏开发
    WebAssembly 可用于在浏览器中运行高质量的 3D 游戏和游戏引擎,如 UnityUnreal Engine
  2. 高性能计算
    适合需要高性能的应用程序,例如科学模拟、视频解码、加密运算等。
  3. 跨平台应用迁移
    将桌面或服务器端的应用迁移到 Web 环境,例如 PDF 处理工具、CAD 应用等。
  4. 前端性能优化
    在前端代码中使用 WebAssembly 加速计算密集型任务(如数据处理和复杂算法)。

怎么写

运行流程

  1. 编写代码(如 C、C++、Rust)。
  2. 使用编译器(如 Emscripten、Rust 编译器)将代码编译为 WebAssembly 二进制文件(.wasm)。
  3. Web 应用中使用 JavaScript 加载并运行 WebAssembly 模块。

编写步骤

我只会 js 技术栈,怎么编写 wasm 呢 ?

毫无疑问,您可以首选 AssemblyScript,并最终将其编译为可执行的 wasm 文件

Step 1:编写 AssemblyScript 代码

assembly/index.ts

// The entry file of your WebAssembly module.

// 求和计算
export function add(a: i32, b: i32): i32 {
  return a + b;
}

// 递归斐波那契
export function fibonacci(n: i32): i64 {
  if (n <= 1) return n

  return fibonacci(n - 1) + fibonacci(n - 2)
}

Step 2:编译成 wasm 文件

执行下面编译命令,将 AssemblyScript 编译为 .wasm 文件

asc assembly/index.ts --target release

怎么用

Vite 5+ 构建

Step 1:加载并解析 wasm 资源

import wasmUrl from '/wasm/release.wasm?url'

let wasmExports = null

function fetchWasmUrl(wasmUrl = '') {
  return new Promise((resolve, reject) => {
    axios.get(wasmUrl, {
      responseType: 'arraybuffer',
      withCredentials: true
    })
      .then(async (response) => {
        try {
          // 将 ArrayBuffer 数据转化为 WebAssembly 模块
          const wasmModule = await WebAssembly.instantiate(response.data)

          resolve(wasmModule)
        } catch (e) {
          reject(e)
        }
      })
      .catch((e) => reject(e))
  })
}

// 实例化 wasm 资源
const reifyWasm = () => {
  fetchWasmUrl(wasmUrl)
    .then(({ instance }) => {
      wasmExports = instance.exports
    })
}

reifyWasm()

Step 2:执行 wasm 暴露的方法

// 使用 wasm 导出的函数
const output = wasmExports.fibonacci(12)

console.log(output)