Some days ago I have written an article about writing frontend in Go.
Frontend development in Go and WebAssembly is very fun and quite easy to start with but inconvenient during continous app development. You have to type long commands, optimize bundle, write your own server, etc.
I have written a CLI that solves this problem. Let me introduce it, go-web-app
.
Sounds cool, what is it?
go-web-app
is a simple CLI for comfortable web development in Go. It has commands for creating a new app, building to WebAssembly and starting a development server. Later I'll add some more commands and features.
For building binaries it uses TinyGo.
For Go WASM support it uses TinyGo's wasm_exec.js
file.
I wanna try it!
Before installing go-web-app
you need to have TinyGo installed. Install here.
CLI is quite easy to install, just run the script:
curl https://raw.githubusercontent.com/talentlessguy/go-web-app/master/install.sh | bash
And try it:
gwa
It should output something like this:
NAME:
go-web-app - Simple CLI for setting up Go WebAssembly frontend app.
USAGE:
gwa [global options] command [command options] [arguments...]
VERSION:
0.0.2
AUTHOR:
v1rtl (twitter.com/v1rtl)
COMMANDS:
init Initialize a web app
build Compile Go to WebAssembly
dev Run a development server
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--help, -h show help
--version, -v print the version
As you can see, there are 3 main commands - init
, build
and dev
. Let's start from init
.
Create a new app
Simply type:
gwa init <app name>
and it will create a new app. Instead of <app name>
enter your app's name, for example "app".
And you will see this output:
Great! Our project is located in app
.
We need to go to our project, using cd
:
cd app
App structure
Hm, what we see here? There is an src folder with Go files, empty build folder, JavaScript file and HTML file.
index.html
This file is an entry for loading WASM binaries. It contains some styles and, most importantly, WebAssembly loader.
WebAssembly.instantiateStreaming
might not work in your browser if you use legacy, so better update it to latest version or use Chrome / Mozilla / Opera instead. However, I included a polyfill in case you don't want to update.
You can remove these styles in <style>
tag if you don't need them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Go WebAssembly App</title>
<style>
body {
margin: 0;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
font-family: sans-serif
}
</style>
</head>
<body>
<script src="wasm_exec.js"></script>
<script>
// Polyfill
if (!WebAssembly.instantiateStreaming) {
WebAssembly.instantiateStreaming = async (res, obj) => (
await WebAssembly.instantiate(await (await res).arrayBuffer(), obj)
)
}
const go = new Go()
WebAssembly.instantiateStreaming(fetch('/build/out.wasm'), go.importObject).then(result => {
go.run(result.instance)
WebAssembly.instantiate(result.module, go.importObject)
})
</script>
</body>
</html>
src
There are all the go files in src. If you put your code outside the directory it won't work. So better keep everything related to code in src.
After creating the app, we can see main.go file here. It is "Hello World" to ensure that everything works.
Here's how it looks like:
package main
import "syscall/js"
func main() {
document := js.Global().Get("document")
document.Get("body").Set("innerHTML", "<h1>Congrats!</h1><h2>You just created a new app using <code>go-web-app</code> π</h2><a href='https://github.com/talentlessguy/go-web-app'>Star the project β</a>")
}
We import "syscall/js"
to access JavaScript environment, then set innerHTML
property to that HTML code.
Equiualent in JS:
document.write('<h1>Congrats!</h1><h2>You just created a new app using <code>go-web-app</code> π</h2><a href='https://github.com/talentlessguy/go-web-app'>Star the project β</a>')
HTML Code here looks messy because I couldn't escape backtick symbol. This is how it should look:
<h1>Congrats!</h1>
<h2>You just created a new app using <code>go-web-app</code> π</h2>
<a href='https://github.com/talentlessguy/go-web-app'>Star the project β</a>
Now we need to compile our Go code.
Compile to WebAssembly
go-web-app
uses TinyGo so WebAssembly output is super small and loads quite fast.
For building binaries we use gwa build
. It takes all the go files from src and puts to build/out.wasm.
Type the command to see result:
gwa build
WebAssembly is available in build directory. It weights ~20Kb. You can check output size by yourself:
du -sh build
As you can see in CLI output, it says that we should start a development server. Let's do it.
Start the app
Dev server is basically a static file server that uses http.FileServer
to serve files and also HTML.
To launch the server, type this command and pick a port you want. Otherwise, go-web-app
will start on 8080.
gwa dev --port 80
Navigate to https://localhost, and you'll see this:
You don't need to open and close the server each time you build new binaries, server auto updates already. You only need to press Ctrl + R
to reload the page.
Later, I'll maybe implement the mechanism of autoupdate using WebSockets.
To close the server, type Ctrl + C
.
Conclusion
That's all. Please let me know if CLI is easy enough to use, what I should add / remove from it.
Also, you can support the project by hitting a star on GitHub.
Discussion (1)
Very Cool!