Open13

wails + Next.js でアプリケーションを作る

MaretolMaretol

やってみよう的記事

Wailsに関してはざっくりした理解しかない(勉強2日目)のでそのへんもメモしながらやっていく

ターゲット環境はWindowsだが、開発環境はWSL2でやっている

MaretolMaretol

まず開発環境の構築

https://wails.io/docs/gettingstarted/installation

概ね公式ドキュメントに従えばいい。とりあえずGoとNPMの環境は作っておく必要あり(もともとあったので割愛)

WSL2の場合、Linuxの条件に合わせれば特に問題ない(なかった)

go install github.com/wailsapp/wails/v2/cmd/wails@latest

でインストールしたwailsで wails doctor コマンドを叩けば何が足りないか出るため、足りないものをインストールすればよい。WSL2でUbuntuならapt installで指示されたものを入れれば普通に環境構築が完了する(した)

この辺は特に詰まらないと思う。ちなみに開発環境はWSL2だが最終的にWindows向けビルドをしたいので今後またなにか入れることになると思う(なんでそんな面倒なことを……)

MaretolMaretol

次。プロジェクトを作成する

今回はNext.jsかつApp routerを使いたい(知見があるので)という理由でテンプレートはサードパーティのものを利用する

https://github.com/thisisvk-in/wails-template-nextjs-app-router

これを使う。これはNext.js14で作られているので使わせてもらう

ちなみに他のテンプレートもある

https://wails.io/docs/community/templates

お好みで(ただし上記の通り安全性は自分で確認)

wails init -n "Your Project Name" -t https://github.com/thisisvk-in/wails-template-nextjs-app-router

これでできたプロジェクトに移動し一旦 wails dev で開発環境を起動させる

MaretolMaretol

初回起動時は go mod tidy や npm install が走るためちょっと時間がかかる

あとちなみにだが、WSL2で動いているこのdev環境は当然LinuxのGUIアプリケーションとして動く

WSL2だとLinuxのデスクトップ向けアプリケーションも動かしてくれて、普通にウィンドウが表示される(マウスポインタとかウィンドウのUIがLinuxになってる)。普通に動いてくれるのでありがたい

MaretolMaretol

あと起動したら(なぜか)画像ファイルがないのでそこだけ表示されなかった

まあ問題ないのでスキップする(staticなデータをどう扱うべきかは一旦置いておく。たぶんNext.jsのpublicディレクトリに置くことになるはず……

MaretolMaretol

起動に成功したらfrontendのディレクトリに移動し一通りアップデートを掛ける

$ cd frontend
$ npm install next@14.2.28
$ npm audit fix

Next.jsは15に対応してるかわからないので一旦14系の最新のものに上げる。ついでにaudit fixもかける

現状(2025-05-06時点)ではこれで0 vulnerabilitiesになるのでセキュリティ的にも安心

MaretolMaretol

続いてshadcnを入れる(これは人によっては不要かもしれないが私は使ってるので入れる)

上記と同様 frontend のディレクトリで実行する。初期化とボタンコンポーネントの追加

$ npx shadcn@latest init
$ npx shadcn@latest add button

で、いい感じにコンポーネントを書いてあげると動くのが確認できる

MaretolMaretol

これでまあある程度の環境構築は完了するのであとはwailsのドキュメントに従ってあれこれ作ればいい

ひとまず落ち着いたのでちょっとだけwailsの話をする


wailsは、めちゃくちゃざっくりいうとWeb技術のフロントをWebviewで表示し、バックエンドにGoを置くというスタイルのクロスプラットフォームネイティブアプリのフレームワーク

フロント部分はWeb技術なら何でもいいらしく、公式でもReact、Vue.js、Svelte、その他HTML+JavaScriptなどの環境でも動く

細かい部分はまだ追いきれてないが、Goで実装した関数や構造体に対して自動で対応するTypeScriptの型情報込のインターフェースを生成してくれるのでとても楽。どのように実行してるかは今後調べていく

なぜwailsを採用したのか、という点に関しては「プライベートでGoを使ってアプリケーション開発をしたかった」というのが理由

比較として考えたものに、wasmビルド、cgoを使ってのdll/soビルド等を考えたが、Goは現状wasmとあまり相性が良くなったという感想を抱いたのが1つ(バックエンド側のwasmならいくらか良さそうだがフロントだとやや辛い印象)、cgoはGoと離れたところでの問題があったり型情報の都合があまり自由が効かなかったりと辛い印象が強かった

wailsは初見ではビルド環境を整えたりするのが大変そうかと思ったが、意外とあっさり整えられてビルドもすんなり通った。WSL2に開発環境を置いていたのでその点も不安要素だったがこちらも簡単に解決できたため一旦これでやってみようと思った次第

Next.jsは個人サイトを作るときにも使っていたためこれが使えればいいなと思ったらこちらもサードパーティのテンプレートだが対応したものがあったためそちらを採用

あとは開発環境をもうちょっと整備したらより効率的に開発できそうなので一旦これで進めてみようと思った次第


あと完全に余談だが、Go自体の向き不向きはやはり強い

wasm/wasiは今後完成度が上がればいいかもしれないが、Go自体が「基本全部Goで済まそう」的な思想強めなためこのように外と協力する土台を使っていい感じに動く環境を作れるのかわからない

もともとサーバサイド向きで、アプリケーションを書いてビルド+成果物を最低限のDockerコンテナに置いてデプロイ、スケーラビリティも高くしやすく少人数の開発向き、というGoの良さはこういうところでちょっとだけマイナスに働く感じ

まあプライベートでもGoを書きたい(TypeScriptが一番書いてる)という欲から手を出したので、今後どっかで詰む可能性はある

ひとまず作りたいものが作れるかを検証するところから始めていく

MaretolMaretol

ちなみに対応プラットフォームはmac/Linux/Windowsになっているが、今後Android/iOSも対応する予定らしい

技術的にはWebviewなので、込み入ったアプリケーションとかは作れないが、簡易なWebアプリと同等ぐらいで作りたいなら問題はない……と今のところ思う。これからなんか出てくる可能性はある

MaretolMaretol

環境整備メモ

高解像度環境でのスケーリング調整

$ export GDK_SCALE=2
$ export GDK_DPI_SCALE=0.75
MaretolMaretol

VSCodeを使ってるのでワークスペース定義で frontend ディレクトリを切っておくといろいろ便利

prettierも追加&設定しておくと楽。保存時に自動で整形してくれる

code-workspace
{
	"folders": [
		{
			"path": "."
		},
		{
			"path": "frontend",
		}
	],
	"settings": {
		"[javascript]": {
			"editor.tabSize": 2,
			"editor.defaultFormatter": "esbenp.prettier-vscode"
		},
		"[typescript]": {
			"editor.tabSize": 2,
			"editor.defaultFormatter": "esbenp.prettier-vscode"
		},
		"[javascriptreact]": {
			"editor.tabSize": 2,
			"editor.defaultFormatter": "esbenp.prettier-vscode"
		},
		"[typescriptreact]": {
			"editor.tabSize": 2,
			"editor.defaultFormatter": "esbenp.prettier-vscode"
		},
		"[json]": {
			"editor.tabSize": 2,
			"editor.defaultFormatter": "esbenp.prettier-vscode"
		},
		"[jsonc]": {
			"editor.tabSize": 2,
		},
		"editor.formatOnSave": true,
		"files.associations": {
			"*.css": "tailwindcss"
		}
	}
}

あと.gitignoreが不完全なので諸々追加する

MaretolMaretol

ちまちまGo側に実装を進めて一段落ついたのでアクセスハンドラー的な構造体をバインドして TypeScript 側のインターフェースを作成

このときGo側では問題にならない単語がTypeScript側では予約語だったためエラーが起きるなどした。こういう問題もあるのねということでGo側を変更し再度生成&成功