Fable on Wails

FableはF#コードのJavaScriptトランスパイラだ。要するにTypeScriptみたいなもん。

fable.io

WailsはフロントエンドにWebViewを使うGoのマルチプラットフォームデスクトップアプリケーションフレームワークだ。要するにElectronやTauriみたいなもん。

wails.io

あとはわかるな。

今回の環境はWindows11のgit bashで次の通り。ほかの環境でもほぼ同じでいけそうな気がするので各自読み替えてくれたし。

$ dotnet --version
7.0.100

$ go version
go version go1.19.4 windows/amd64

$ node -v
v18.10.0

Fableのテンプレートをインストール。ちなみにFableはまだ.NET 7に対応できてないようだが、今はデフォルト設定で.NET 6になるので問題ないっぽい。

$ dotnet new --install Fable.Template

Wailsをインストール。

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

まずはWailsアプリとして生成する。オプションは何でもいいのでお好みで。ただし今回はシンプルにするためにテンプレートはデフォルトにしておく。

$ wails init -d hello -n hello -g -ide vscode
$ cd hello

生成されたフロントエンドを消してFableで生成したものに置き換える。

$ cd frontend
$ rm -rf *
$ dotnet new fable

FableはWebpackでビルドするようになっているのでWailsのViteでビルドするように変更する。

--- a/frontend/package.json
+++ b/frontend/package.json
@@ -2,13 +2,13 @@
   "private": true,
   "scripts": {
     "postinstall": "dotnet tool restore",
-    "start": "dotnet fable watch src --run webpack-dev-server",
-    "build": "dotnet fable src && webpack"
+    "dev": "dotnet fable watch src -s --run vite",
+    "build": "dotnet fable src --run vite build",
+    "preview": "dotnet fable src --run vite preview"
   },
   "devDependencies": {
-    "webpack": "^5.75.0",
-    "webpack-cli": "^4.10.0",
-    "webpack-dev-server": "^4.11.1"
+    "vite": "^2.9.9"
   },
   "version": "1.0.0"
 }
$ rm webpack.config.js
$ npm install

Fableの静的ファイルをWailsに合わせる。

$ mv public/* .
$ rmdir public
--- a/frontend/public/index.html
+++ b/frontend/index.html
@@ -10,6 +10,6 @@
     <p>Fable is running</p>
     <p>You can click on this button:</p>
     <button class="my-button">Click me</button>
-    <script src="bundle.js"></script>
+    <script src="./src/App.fs.js" type="module"></script>
 </body>
 </html>

ソースマップが吐かれるのでコミットしないように。

--- a/frontend/.gitignore
+++ b/frontend/.gitignore
@@ -1,6 +1,7 @@
 # Fable generated files
 .fable
 *.fs.js
+*.fs.js.map
 bundle.js
 temp/**

いざ開発モードで実行。ビルドが成功してウィンドウが表示されればOK。

$ cd ..
$ wails dev

とりあえず最小だとこんな感じになりそうだけど、よくわかってないとこはおいおい。Wailsのランタイムとの相互運用性とかFableでFelizやElmishを使うのとかを今後試していく。