Wails でデスクトップアプリを作る #7 フロントエンドフレームワークを付ける — Svelte・Vue・React
本編の 6 編(#1〜#6)はバニラの JavaScript で前側を作りました。概念を学ぶにはそれが最も無駄がありませんが、画面が増えて状態が絡む実際のアプリではフレームワークが楽です。この応用編は Wails に Svelte・Vue・React のようなフロントエンドフレームワークを付ける方法を扱います。実践トラックが「軽量なコンポーネントフレームワークを前提にする」として飛ばした、まさにその箇所をここで埋めます。
このシリーズは本編 6 編 + 応用 2 編、全 8 編です。
- 本編: #1 · #2 · #3 · #4 · #5 · #6
- 応用: #7 フロントエンドフレームワークを付ける — Svelte・Vue・React ← この記事 · #8 デバッグ — 開発者ツール・ログ・よくあるエラー
Wails がフロントエンドを選ばないということ #
#2 で見たように、Wails プロジェクトは Go のルートと frontend ディレクトリに分かれます。Wails はこの frontend ディレクトリの中で何を使おうと気にしません。Wails が要求するのはちょうど二つ、つまりフロントエンドをインストールするコマンドとビルドするコマンドだけです。この二つは wails.json に書かれています。
{
"frontend:install": "npm install",
"frontend:build": "npm run build"
}wails dev や wails build はこのコマンドを呼んでフロントエンドを準備し、その成果物(静的ファイル)を最終バイナリにまとめます。だから Vite でビルドされるフレームワークなら何でも自然に噛み合います。Svelte、Vue、React、Solid すべてこの構造の中で同じです。
wails init テンプレートで始める #
新しいプロジェクトなら、最初からフレームワークのテンプレートで始めるのが最も簡単です。wails init の -t オプションにテンプレート名を渡します。
wails init -n myapp -t svelte # または svelte-ts
wails init -n myapp -t vue # または vue-ts
wails init -n myapp -t react # または react-ts
wails init -n myapp -t vanilla # 本編で使った既定-ts が付いたテンプレートは TypeScript 版です。テンプレートは frontend をそのフレームワークと Vite であらかじめ構成してくれるので、生成した直後に wails dev するだけでホットリロードの開発ループがそのまま動きます。どのフレームワークを選んでも、Go 側のコード(#3 のバインディング、#4 のランタイム)はまったく変わりません。
バインディングはフレームワークと無関係に同じ #
Wails が Go のメソッドをフロントエンドの関数として公開する方式(#3)は、フレームワークと関係なく同一です。wailsjs フォルダに自動生成されるバインディングを import して呼べばよいです。以下は同じ Greet の呼び出しを三つのフレームワークで使う様子ですが、違うのは状態を画面につなぐ方法だけです。
<script>
import { Greet } from "../wailsjs/go/main/App";
let name = "", result = "";
async function greet() { result = await Greet(name); }
</script>
<input bind:value={name} />
<button on:click={greet}>あいさつ</button>
<p>{result}</p><script setup>
import { ref } from "vue";
import { Greet } from "../wailsjs/go/main/App";
const name = ref(""), result = ref("");
const greet = async () => { result.value = await Greet(name.value); };
</script>核心は import { Greet } from "../wailsjs/go/main/App" の 1 行が三つのフレームワークで同じだということです。Go のメソッドを呼ぶ部分は共通で、bind:value(Svelte)や ref(Vue)のように結果を画面に反映する方式だけがフレームワークごとに異なります。実践トラックでデータの真実を Go に置き、フロントエンドは画面だけを担うとした理由がここで明確になります。どのフレームワークでも Go を呼ぶ方法は一つだからです。
何を選ぶか #
- バニラ: 依存がなくバンドルが最も小さいです。本編のように状態が単純なツールに適します。
- Svelte: 軽くてリアクティブが文法に溶け込んでいて、デスクトップアプリの小さいバンドルとよく合います。
- Vue・React: エコシステムとコンポーネントの資産が大きく、チームがすでに慣れているなら学習コストが 0 です。
正解はチームがすでに使っているものです。新しく学ぶ必要があるなら、デスクトップアプリはバンドルサイズと単純さが重要なので、バニラか Svelte から始めて必要なときに育てるのが無難です。
バニラのアプリに後から付ける #
すでにバニラで始めたアプリにフレームワークを加えたいなら、frontend ディレクトリをそのフレームワークの Vite プロジェクトに置き換え、wails.json のビルドコマンドが合っているか確認すればよいです。このとき Vite のビルド出力パスが Wails の期待する場所(frontend/dist)と合う必要があり、ずれると #8 で扱う「ウィンドウは開くのに画面が空」の症状が出ます。
まとめ #
- Wails はフロントエンドを選びません。
wails.jsonのインストール・ビルドコマンドの二つが合えば、Vite でビルドされるどのフレームワークでも噛み合います。 - 新しいプロジェクトは
wails init -t svelte|vue|react(または-ts版)で始めるのが最も簡単です。Go 側のコードはフレームワークと無関係にそのままです。 - バインディングの呼び出し(
import { Greet } from "../wailsjs/...")は三つのフレームワークで同一です。違うのは結果を画面につなぐ方式だけです。 - 選択はチームが使うものを優先し、新しく学ぶならバンドルが小さいバニラ・Svelte がデスクトップに無難です。
- バニラに後から付けるときは Vite の出力パスを Wails の期待する場所に合わせます。ずれると空の画面になります。
- 次の記事では、この問題を含むよくあるエラーを開発者ツールとログで捕まえるデバッグを扱います。