背景

最近在做rosbag的可视化工具,网上找了个源码参考(foxglove)。成功down下来,跑起来了。于是乎,开始研究前后端代码;结果居然花了一下午没找到后端代码,不明白为什么纯web页面就可以解析rosbag(以前都是用node.js或者c++代码解析的)。

过程

在找了一下午之后,又回到了老办法;看netork,果然还是除静态资源外没找到任何一条http请求,懵逼了;但是我看到一个很奇怪的东西

web页面中直接调用c++/c/go代码?【wasm】_Go

接下来,就开始查资料。推测解析bag的代码一定跟这个wasm有关联。

wasm介绍

WebAssembly(简称 WASM)是一种高效的、低级的字节码格式,用于在网页浏览器中运行代码。它是一种可移植的二进制格式,设计用来在Web环境中提供接近原生性能的执行速度。

WebAssembly 的特点包括:

  1. 高性能:WASM 可以在浏览器中接近原生代码的执行速度运行,适用于高性能计算任务,如游戏、图形处理和数据分析等。
  2. 可移植性:它是跨平台的,可以在任何支持 WebAssembly 的浏览器和环境中运行,不同操作系统和设备之间的兼容性很好。
  3. 安全性:WASM 运行在一个受限的沙箱环境中,与主机系统隔离,这样可以提高安全性,避免恶意代码对系统的破坏。
  4. 易于集成:它可以与 JavaScript 互操作,允许开发者将已有的 C/C++、Rust 等语言编写的代码编译为 WASM 模块,并在 Web 应用中调用这些模块。
  5. 快速加载:由于其紧凑的二进制格式,WASM 模块可以比传统的 JavaScript 代码加载得更快,提高了网页的响应速度。

使用场景:

  • 游戏开发:由于其高性能,WASM 适用于 Web 上的游戏和图形密集型应用。
  • 编译型语言的运行:可以将 C、C++、Rust 等编译成 WASM,从而在 Web 上运行这些语言的代码。
  • 计算密集型任务:如图像处理、数据分析等。

总的来说,WebAssembly 提供了在 Web 环境中实现高效、可移植的代码执行的能力,是现代 Web 开发的重要组成部分。

推测

解析rosbag部分的代码必是被打包成wasm,然后web页直接调用方法了。

实现一个wasm

本机正好用go环境,于是用go实现了一下。将go打包成wasm文件,html页面直接调用:

test.go
package main

import (
    "syscall/js"
)

func main() {
    c := make(chan struct{}, 0)
    js.Global().Set("test", js.FuncOf(func(this js.Value, p []js.Value) interface{} {
        return js.ValueOf("Hello, WASM!")
    }))
    <-c
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
打包命令
$env:GOARCH = "wasm"
$env:GOOS = "js"
go build -o test.wasm test.go
  • 1.
  • 2.
  • 3.

得到一个test.wasm文件

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Go WASM Example</title>
</head>
<body>
<h1>Go WASM Example</h1>
<script src="wasm_exec.js"></script>
<script>
    const go = new Go();

    async function loadWasm() {
        try {
            // 加载并实例化 WASM 模块
            const wasmResponse = await fetch('test.wasm');
            const wasmBuffer = await wasmResponse.arrayBuffer();
            const result = await WebAssembly.instantiate(wasmBuffer, go.importObject);

            // 运行 Go 实例
            go.run(result.instance);

            // 调用 Go 导出的函数
            console.log(window.test());  // 这将输出 "Hello, WASM!"
        } catch (err) {
            console.error('Error loading WASM module:', err);
        }
    }

    loadWasm();
</script>
</body>
</html>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.

效果

web页面中直接调用c++/c/go代码?【wasm】_WebAssembly_02

感触

是不是以后一个静态文件就可以包含前后端的代码了?

长风破浪会有时,直挂云帆济沧海