Golang与Svelte结合使用Wasm的经验分享

Golang与Svelte结合使用Wasm的经验分享 有没有人在尝试结合 Svelte 和 Golang/Wasm 或 TinyGo/Wasm?

我想了解与 Svelte 一起使用的方案。我已经在 Svelte 中实现了一个“Hello World”示例,但如果有谁已经进行了更深入的探索,我很想知道你们是如何选择实现方式的,以及是否有人开发了打包插件(我知道有一个用于 webpack 和 Go 的插件,但还没有专门为 Svelte 设计的)。

2 回复

我创建了一个快速启动模板,用于构建带有Svelte前端的Go WebAssembly应用:

GitHub

GitHub - happybeing/svelte-go-wasm-webpack: 用于Golang WebAssembly应用与Svelte前端的快速启动模板

用于Golang WebAssembly应用与Svelte前端的快速启动模板 - GitHub - happybeing/svelte-go-wasm-webpack: 用于Golang WebAssembly应用与Svelte前端的快速启动模板

这使用了我的一个适用于Go v1.13的webpack插件分支(其中也包含了展示如何将其与React或node CLI一起使用的示例)。

Webpack plugin for Golang v1.13 WebAssembly including examples for CLI (NodeJS) and web (React or Svelte) I’ve forked and updated the webpack Go wasm plugin for Golang v1.13 and added a Svelte example:

这是我想制作一个去中心化git门户(github替代品)的巧妙计划的一部分,该门户在浏览器中运行,使用p2p存储(因此是静态HTML且无需服务器)。如果有兴趣,请参见这里

更多关于Golang与Svelte结合使用Wasm的经验分享的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Svelte项目中集成Golang/Wasm是可行的方案,以下是具体实现示例:

1. Go/Wasm端代码

// main.go
package main

import (
    "syscall/js"
)

func add(this js.Value, args []js.Value) interface{} {
    if len(args) != 2 {
        return js.ValueOf(nil)
    }
    a := args[0].Float()
    b := args[1].Float()
    return js.ValueOf(a + b)
}

func registerCallbacks() {
    js.Global().Set("goAdd", js.FuncOf(add))
}

func main() {
    c := make(chan struct{}, 0)
    registerCallbacks()
    <-c
}

编译为Wasm:

GOOS=js GOARCH=wasm go build -o main.wasm main.go

2. Svelte端集成

<!-- App.svelte -->
<script>
  let wasmModule;
  let result = 0;
  let a = 5;
  let b = 3;

  async function loadWasm() {
    const go = new Go();
    const response = await fetch('main.wasm');
    const bytes = await response.arrayBuffer();
    const { instance } = await WebAssembly.instantiate(bytes, go.importObject);
    go.run(instance);
    wasmModule = instance.exports;
  }

  function calculate() {
    if (window.goAdd) {
      result = window.goAdd(a, b);
    }
  }

  onMount(() => {
    loadWasm();
  });
</script>

<main>
  <h1>Go/Wasm + Svelte</h1>
  <input type="number" bind:value={a} />
  <input type="number" bind:value={b} />
  <button on:click={calculate}>计算</button>
  <p>结果: {result}</p>
</main>

3. Vite配置(推荐)

// vite.config.js
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';

export default defineConfig({
  plugins: [svelte()],
  server: {
    headers: {
      'Cross-Origin-Opener-Policy': 'same-origin',
      'Cross-Origin-Embedder-Policy': 'require-corp'
    }
  }
});

4. 使用TinyGo的优化版本

// 使用TinyGo编译(更小的Wasm体积)
// tinygo build -target=wasm -o main.wasm main.go

5. 构建脚本示例

// package.json片段
{
  "scripts": {
    "build:go": "GOOS=js GOARCH=wasm go build -o public/main.wasm ./wasm",
    "dev": "npm run build:go && vite",
    "build": "npm run build:go && vite build"
  }
}

6. 直接内存操作示例

// 高性能数据交换
func processData(this js.Value, args []js.Value) interface{} {
    dataPtr := args[0].Int()
    length := args[1].Int()
    
    // 从内存中读取数据
    data := make([]byte, length)
    js.CopyBytesToGo(data, js.ValueOf(dataPtr))
    
    // 处理数据
    for i := range data {
        data[i] = data[i] * 2
    }
    
    // 写回内存
    js.CopyBytesToJS(js.ValueOf(dataPtr), data)
    return nil
}

这个方案不需要专门的Svelte插件,通过标准的WebAssembly API即可实现集成。关键点包括正确配置HTTP头以支持Wasm,以及通过JavaScript全局对象进行Go/Svelte间的函数调用。

回到顶部