GoでVueっぽくWebアプリが作れるVugu事始め

[ツイートが100RT超えた](https://twitter.com/goofmint/status/1112987133365481472)ので、Qiitaにも書いてみます。

Go 1.11がJavaScript APIをすべてサポートしたライブラリを開発し、WebAssemblyに新しい未来が見えました。それまでのWebAssemblyはDOMやネットワーク操作ができないとされてきたので、ループ処理の高速化や数値計算、またはCanvasをゴリゴリ使うゲームくらいしか使い道がないよね…といった評価でした。しかしJavaScript APIが実装されたことで、DOM操作やネットワーク処理が可能になり、WebアプリケーションをそのままGoに置き換えられるんじゃないかという可能性が出てきました。

[GoではじめるWebAssebmly その1「Hello World」 | hifive開発者ブログ](https://blog.htmlhifive.com/2018/12/14/webassembly-with-go-1-hello-world/)

とは言え、直接書くとコードがなかなか複雑というか、残念な感じになっていました。例えばネットワークのオンライン、オフラインをイベント通知を受け取る場合のコードは下記のようになります。

```go
  navigator := js.Global().Get("navigator")
  cb1 := js.NewCallback(func(args []js.Value) {
    if navigator.Get("onLine").Bool() {
      println("Network is Online");
    } else {
      println("Network is Offline");
    }

  })
  window.Call("addEventListener", "online", cb1)
  window.Call("addEventListener", "offline", cb1)
```

その内、良い感じにラッピングしたフレームワーク（しかも仮想DOMが使えるような）が出るんじゃないかと思っていたのですが、ついにVuguによって実現しそうです。

[Vugu: A modern UI library for Go+WebAssembly](https://www.vugu.org/)

ということで、Getting startedに沿った進め方を紹介します。

## Go 1.12のインストール

VuguはGo 1.12が必須です。ということでインストールします。[goenv](https://github.com/syndbg/goenv) を使うと楽ちんです。

```
$ goenv install 1.12
$ goenv local 1.12
```

## go.modの作成

go.mod というファイルを作ります。内容は次の通りです。

```
module example.org/someone/testapp
```

## root.vuguの作成

root.vuguはWeb Component風にUI、Goがまとまったファイルになります。たぶん画面ごとにvuguファイルを作っていくのでしょう。root.vuguの内容は次の通りです。

```html
<div class="my-first-vugu-comp">
    <button @click="data.Toggle()">Test</button>
    <div vg-if="data.Show">I am here!</div>
</div>

<style>
.my-first-vugu-comp { background: #eee; }
</style>

<script type="application/x-go">
type RootData struct { Show bool }
func (data *RootData) Toggle() { data.Show = !data.Show }
</script>
```

見て分かりますが、scriptタグがapplication/x-goになっていて、その中はGoを記述します。RootDataを定義しておいて、それがイベント時に送られてくるので、その内容を書き換えるといった具合です。Vueとはちょっと書き方が違いますが、分からないものでもないでしょう。

## 開発用サーバを作る

ここは単純なGoです。`devserver.go` というファイルで作りますが、名前は何でも良いです。

```go
// +build ignore

package main

import (
	"log"
	"net/http"
	"os"

	"github.com/vugu/vugu/simplehttp"
)

func main() {
	wd, _ := os.Getwd()
	l := "127.0.0.1:8844"
	log.Printf("Starting HTTP Server at %q", l)
	h := simplehttp.New(wd, true)
	// include a CSS file
	// simplehttp.DefaultStaticData["CSSFiles"] = []string{ "/my/file.css" }
	log.Fatal(http.ListenAndServe(l, h))
}
```

## 実行する

では実行します。単に実行するだけでvuguのダウンロードも行ってくれる辺り、Goは素晴らしいですね。

```
$ go run devserver.go
```

これで http://localhost:8844 でサーバが立ち上がります。

## アクセスする

では実際にアクセスします。アクセスすると最初にローディングが走って、Webの画面が表示されます。このローディングの時にWebAssemblyやGoファイルが生成されます。

![Untitled3.gif](https://qiita-image-store.s3.amazonaws.com/0/197026/bebf9b0e-6141-7ece-eda9-9895de54e706.gif)

Hot reloadはないですが、HTTPサーバは落とさずに再読み込みするだけで表示が更新されます。ネットワークを見ると、ちゃんとWebAssemblyファイルが生成されているのが分かります。これは動的なようで、静的ファイルはありませんでした。

<img width="857" alt="Screenshot_ 2019-04-03 10.52.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/197026/4066c533-6aeb-6f8a-5856-f8d31357e83b.png">

## まとめ

Vuguはまだリリースしたてで、Experimentalなステージです。しかし、Goで書けるので型付けがあり、柔軟な書き方ができること、さらにWebAssemblyによって高速なWebアプリケーション（後、普通のJavaScriptより難読化が進んでいる）が作れるのがメリットになるでしょう。何よりVueっぽく書けるのが個人的に一押しポイントです。

なお、DOMやネットワーク操作はWebブラウザ側のJavaScriptで実行されます。WebAssemblyでもDOM書き換えが高速化されたり、CORS制限を越えたネットワークアクセスができる訳ではないのでご注意ください。

ぜひVuguを体験してみてください！

[Vugu: A modern UI library for Go+WebAssembly](https://www.vugu.org/)