Open6

「Wails」を使ったGo+JSのデスクトップアプリ制作

大井さかな大井さかな

環境

❯ sw_vers
ProductName:            macOS
ProductVersion:         14.1
BuildVersion:           23B74
❯ uname -m
x86_64
❯ go version
go version go1.21.4 darwin/amd64
❯ node --version
v20.9.0
❯ npm --version
10.2.3
大井さかな大井さかな

プロジェクト立ち上げ

テンプレートを使用する

% go install github.com/wailsapp/wails/v2/cmd/wails@latest
% wails init -n myproject -t react-ts

こんな内容が作成された

├── .gitignore
├── README.md
├── app.go
├── build/
│   ├── README.md
│   ├── appicon.png
│   ├── darwin/
│   └── windows/
├── frontend/
│   ├── index.html
│   ├── package.json
│   ├── src/
│   ├── tsconfig.json
│   ├── tsconfig.node.json
│   ├── vite.config.ts
│   └── wailsjs/
├── go.mod
├── go.sum
├── main.go
└── wails.json
  • wails.json: プロジェクト設定
  • main.go: メイン。「ウィンドウサイズを指定して起動」のような初期コード。
  • frontend/src: Reactとか画像とかフォントとか
  • fronntend/wailsjs: GoとJSを繋ぐ、自動生成コードとruntimeライブラリ
  • builld/:macOSとWindows固有の配布用ファイル

ちなみにgit initは自分でやらないといけない

大井さかな大井さかな

GoとJSの連携

Bind

JS側からGo側の関数呼び出しができる。JSではこの非同期処理にはPromiseが用いられる。

例えばテンプレでは、wails.RunのオプションBindAppが渡されている。この指定によってAppはフロントエンド側から扱えるようになる。

main.go
err := wails.Run(&options.App{
	Title:  "myproject",
	Width:  1024,
	Height: 768,
	// (中略)
	Bind: []interface{}{
		app,
	},
})

AppのメソッドGreetが定義されている。

app.go
func (a *App) Greet(name string) string {
	return fmt.Sprintf("Hello %s, It's show time!", name)
}

すると、自動的にwailsjsディレクトリ内にコードが生成される

App.d.ts
export function Greet(arg1:string):Promise<string>;

なので、インポートすれば使用できる。

App.tsx
import {Greet} from "../wailsjs/go/main/App";

Greet(name).then(updateResultText);

ここでは引数も返り値もstringだったが、構造体も可能。その場合jsonタグが必要。

https://wails.io/docs/howdoesitwork

Event

イベントでやり取りもできる。発火とリスナー定義は、GoとJSのどちらからもできる。
というかイベントに限らずruntimeが共通化されていて、アプリケーション操作も多くが両側から呼び出せる手軽さがある。

https://wails.io/docs/reference/runtime/events
https://shinshin86.hateblo.jp/entry/2022/08/26/000000