Chapter 14

SPAなシングルバイナリの例

NoboNobo
NoboNobo
2020.11.10に更新

シングルバイナリの利点

主な流れは前チャプターの「APIバックエンド連携」、「サーバーをまとめる」の状態から、
アセットをバイナリにバンドルすれば「シングルバイナリ」にできるという手順です。

こうして作ったバイナリは任意の環境に持って行ってそのUIが利用可能になるので
「デスクトップアプリケーション」のような用途に使うこともできます。

筆者がよく使う場面はlinux、arm64向けにクロスビルド(Goはこの辺りがとても簡単)してRaspberryPiにそのバイナリを転送、RaspberryPi側で自動起動するようにセットアップしておくと、LAN内からならそのUIをブラウザで開くことができます。

こうしてRaspberryPiに乗っている機能をリモートコントロールするUIとして使えます。

brbundleツールのインストール

go get go.pyspa.org/brbundle/...

シングルバイナリ化を想定したプロジェクト

  • single-binary/
    • go.mod
    • dist/ <-フロントエンドをまとめた静的ファイル群の出力先
    • backend/
      • api.go
    • frontend/
      • assets/ <-フロントエンドが利用するアセット
      • index.go
    • server.go
    • embedded-bundle.go <-自動生成ファイル

backendfrontendの内容は前チャプターと同様です。
go.modの内容は以下のようになっていると想定します。

go.mod

module single-binary

go 1.15

バックエンドサーバー実装には埋め込みアセットをサーブするようになっています。
あと、go generateにて以下の処理を書いています。

  • フロントエンドの静的ファイル群をdist/に出力
  • フロントエンドが参照しているアセットリソースをdist/にコピー
  • distにあるファイルを圧縮してembedded-bundle.goに出力

server.go

package main

import (
	"flag"
	"io/ioutil"
	"log"
	"net"
	"net/http"

	"go.pyspa.org/brbundle/brhttp"

	_ "single-binary/backend"
)

//go:generate sh -c "cd frontend && spago deploy ../dist"
//go:generate sh -c "cp -Rf frontend/assets dist/"
//go:generate brbundle embedded -p main dist

func main() {
	http.Handle("/", brhttp.Mount())
	if err := http.ListenAndServe(":8888", nil); err != nil {
		log.Fatal(err)
	}
}

ビルド

> go generate .
> go build -o single-binary .

これでsingle-binaryという大きめの実行ファイルが出力されます。この実行ファイル一つでフロントエンドもバックエンドも動作するサーバーを起動できます。

必要ならGOOS、GOARCHの指定やスタティックリンクの指定を加えます。

例:

> GOOS=linux GOARCH=arm64 go build -tag netgo -o single-binary .

対象がRaspberryPiの場合

  • サーバーのリッスンポートを80にする
  • サーバーを自動起動設定
  • avahi-daemonを自動起動設定

などを実施すると「 http://hostname.local 」でLAN内のPCやスマホからアクセスできます。

brotliについて

brbundleのファイルサービスハンドラは「brotli」というエンコードで圧縮済みの内容をそのままブラウザに返すハンドラです。メジャーブラウザがサポートしているエンコードの中ではトップクラスの圧縮率を誇るエンコード方式です。この方法であればGoのWASM出力が大きいというデメリットをかなり緩和できます。

その代わり圧縮にはgzipなどに比べても多くの時間が必要になります。

実例

https://github.com/nobonobo/spago-slides

マークダウンテキストからプレゼンテーション用スライドを表示するCLIツール。
必要なリソースが1バイナリにパックされているので運用が楽です。

go get github.com/nobonobo/spago-slides
spago-slides markdown.md

これでブラウザで http://localhost:8080 を開くとプレゼンテーションスライドを表示できる。

左右のキーでページ送り、Rキーでコンテンツのリロード。

また、このプレゼンテーション表示はスライド群をただ縦に繋いだドキュメントなので
印刷も工夫次第でできると思う(プリンタ向けCSSを書けば)。

追記

一定の圧縮サイズを超えると、brbundleツールは極端に出力に必要な時間が伸びます。
快適な開発をSpaGoは目指しているので、もう少し手早く圧縮できるツールを探してみました。

この代替ツールにbroccoliというのが使えそうです。こちらは圧縮にかかる時間がかなり短く済むようです。後日このツールで置き換えた内容に更新します。

go get -u aletheia.icu/broccoli