PostHole
Compose Login
You are browsing eu.zone1 in read-only mode. Log in to participate.
rss-bridge 2023-11-10T17:31:06+00:00

WebAssembly with Go: Taking Web Apps to the Next Level


WebAssembly with Go: Taking Web Apps to the Next Level

Ege Aytin

12 min readNov 10, 2023

Press enter or click to view image in full size

You might’ve noticed the increasing chatter around WebAssembly (WASM) in the dev community. Its potential is vast, and we’ve found it invaluable in enhancing our open source project!

Hi everyone, I’m part of the team behind Permify, an open-source infra that helps developers to create and manage granular permissions throughout their applications.

In this article, I’ll demonstrate why and how we integrated WebAssembly (WASM) into our Playground and gained benefits from its collaboration with Golang.

What does this playground do? Well, without diving too deep, its a interactive module of Permify which used for creating and testing authorization models.

Throughout this post, I’ll be sharing:

  • A brief explanation of WASM and the benefits of using it with Go.
  • A peek into what spurred our choice to integrate WASM in Permify.
  • WASM Implementation, including
  • Quick Warm Up: WASM Implementation with Go
  • Deeper Dive: Permify’s WASM Code Breakdown
  • Frontend: Steps to Embed Go WASM in a React Application

By the end, you should have a clearer understanding of why and how we leveraged WASM’s capabilities for our project.

Understanding WebAssembly

WebAssembly (Wasm) has established itself as a pivotal technology, enabling quick and efficient code execution in web browsers and forming a robust bridge between web applications and the high-performance typically associated with native applications.

1. Unveiling WebAssembly:

Wasm acts as a low-level virtual machine, executing a compact binary code that’s translated from high-level languages.

Primary Advantages:

  • Universal Browser Support: Thanks to its support from all major browsers, Wasm delivers consistent performance across diverse platforms.
  • Near-Native Performance: Intentionally designed to execute binary code at a speed akin to native applications, Wasm enhances the responsiveness of web applications considerably.

In our open-source project, Permify, we strategically incorporated Go (also known as Golang) into its foundational core, selecting it for its widely recognized static typing, concurrency handling, and performance optimization. When the development journey led us to craft the Permify Playground, WebAssembly stepped into the spotlight as a crucial element.

2. Blending Go & WebAssembly:

  • Characteristics of Go: Celebrated for its optimal performance and concurrency handling capabilities, Go has carved a sturdy standing within the developer community.
  • Synergy with WebAssembly: The translation of Go code into WebAssembly enables developers to effectively utilize Go’s robust performance and concurrency management directly within the browser, propelling the creation of powerful, efficient, and scalable web applications.

Our journey isn’t just about melding Go and WebAssembly. Moving forward, we’ll unearth why Wasm was pinpointed as the technology of choice for the Permify Playground development and what significant benefits were reaped from this decision.

Why WebAssembly?

The inception of the Permify Playground brought with it a key question: How to showcase our capabilities without being entwined in the complexities and maintenance woes of traditional server architectures? WebAssembly appeared as a shining answer. Adopting this binary instruction format allowed us to:

  • Execute In-Browser: Permify’s playground could operate straight within the browser, sidestepping server maintenance overheads and repetitive API calls, and notably, making ongoing maintenance a breeze in comparison to older server-based approaches.
  • Achieve Peak Performance: Employing WebAssembly ensures that our Go application operates with a level of performance that competes with native applications, enhancing user interactions and bolstering response times.

Harvesting Technical Benefits and Gathering User Feedback

Utilizing WebAssembly in our Permify Playground led us down a path of discernible technical advantages and an embrace from the community:

  • Swift Execution: By side-stepping server interactions and deploying WebAssembly in-browser, we’ve been able to deliver ultra-fast response times.
  • Uncomplicated User Interface: Centralizing our playground in the browser, we’ve dispelled complexities associated with multi-tool workflows, delivering a clean and straightforward user experience.
  • Community Validation: The affirming feedback and positive reception from the developer community stand as validation of our technological choices and implementations.

Join us in the following sections as we delve deeper into the technicalities, feedback, and learnings from our adventure, providing a thorough exploration of our endeavours with WebAssembly.

WASM Implementation with Go

Before we explore Permify’s use of WebAssembly (WASM) and Go, let’s understand their combination in a sample app. What follows is a step-by-step guide to bringing them together, setting the stage for our deeper dive into Permify’s implementation.

1. Transforming Go into WebAssembly:

  • Steps:
  • To get started, ensure you’ve set the WebAssembly build target in Go:
GOOS=js GOARCH=wasm go build -o main.wasm main.go
  • Next, apply optimizations to reduce the file size and enhance performance:
wasm-opt main.wasm --enable-bulk-memory -Oz -o play.wasm
  • Handling Events:

Suppose you want your Go function to react to a button click from your web page:

package main

import "syscall/js"

js.Global().Set("handleClick", js.FuncOf(handleClick))

func handleClick(this js.Value, inputs []js.Value) interface{} {
println("Button clicked!")
return nil

In your HTML, after loading your WebAssembly module:

<button onclick="window.handleClick()">Click me</button>

2. Integrating with Web Pages:

  • Initializing Wasm:

Ensure you have the wasm_exec.js script linked, then instantiate your Wasm module:

<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("play.wasm"), go.importObject).then((result) => {
go.run(result.instance);
});
</script>
  • Interacting with the DOM:

Accessing and modifying web elements is fundamental. For instance, changing the content of a paragraph element from Go would look something like this:

func updateDOMContent() {
document := js.Global().Get("document")
element := document.Call("getElementById", "myParagraph")
element.Set("innerText", "Updated content from Go!")

3. The Gains: Efficiency & Speed:

  • Go’s Goroutines in the Browser:

Imagine having multiple data fetch operations that can run simultaneously without blocking the main thread:

func fetchData(url string, ch chan string) {
// Simulate data fetch.
ch <- "Data from " + url

func main() {
ch := make(chan string)
go fetchData("<https://api.example1.com>", ch)
go fetchData("<https://api.example2.com>", ch)

data1 := <-ch
data2 := <-ch
println(data1, data2)

Navigating through Go and WebAssembly (WASM) showcases a powerful union, merging Go’s concurrent processing with WASM’s rapid client-side execution. The depth explored in our sample app lights the way forward into Permify, where we apply these technological strengths into a scalable, real-world authorization system.

Deeper Dive: Permify’s WASM Code Breakdown

Let’s dive a bit deeper into the heart of our WebAssembly integration by exploring the key segments of our Go-based WASM code.

1. Setting up the Go-to-WASM Environment

involves preparing and specifying our Go code to be compiled for a WebAssembly runtime.

// go:build wasm
// +build wasm

[...]


*Original source*

Reply