TIGの伊藤真彦です。
最近はFlutterの研究を進めており、一人Flutter連載のような動きをしています。
FlutterをElectronと組み合わせる
- 入門記事: Flutterであればデスクトップアプリケーションを構築できることを説明しました
- Electronの入門記事: これも私が書きましたが、Electronもクロスプラットフォームのデスクトップアプリケーションを開発できるライブラリです
ElectronはHTML、JavaScriptをアセットとして利用してデスクトップアプリケーションとして動かすことができます、結論としてはFlutterアプリケーションをWeb向けにビルドして、その成果物をElectronアプリケーションとしてビルドできました。
なぜそのような事を行うかというポイントですが2点あります。
- Flutter on Desktop未対応の機能を使いたい
- Electron向けの資産を活かしたい
Flutter on Desktop未対応の機能を使いたい
Flutter on Desktopはまだまだリリースから間もないため、安心して利用できるか見極めながら開発していく必要があります。
またFlutter向けパッケージのいくつかはFlutter on Desktopに対応していないものもあります。
例えば先日の記事で技術検証したgoogle_maps_flutterを利用したアプリケーションをデスクトップ向けにビルドすると、執筆時点ではアラートが表示され正常に動作しません。
同じソースコードをWeb向けにビルドし、Electronに組み込むと問題なく動作します。
Flutter on Desktopのエコシステムが充実するまでの繋ぎとしてこのような手法をとることができます。
Electron向けの資産を活かしたい
ビジネス要件的にどうしても必要な、Electronに向け最適化されたJavaScript、TypeScript製モジュールがありました。これらの資産をDart向けに作り直す必要をなくす、という意味でFlutter on Electronという組み合わせが実現できないかな、という検証を行ったという背景もあります。
あまり頼りすぎるとFlutter on Desktopに本格移行する難易度が跳ね上がりますが、この組み合わせであれば既存の資産や豊富なnpmモジュールを活用できます。
Flutter on Desktopのおさらい
Flutterアプリケーションをデスクトップアプリケーションとして動かすことはとても簡単にできます。
起動時、ビルド時のターゲットを指定するだけです。
flutter create myapp |
設定でデスクトップ向けのビルドが有効化されていない場合はconfig
コマンドで有効化します。
flutter config --enable-macos-desktop |
既存のプロジェクトで有効化する場合はconfig
で有効化した後にカレントディレクトリでcreate
コマンドを実行すると、対象のプラットフォーム向けの設定ファイルが用意されます。
flutter create . |
この辺りの手軽さはやはり素晴らしいと感じますね。
FlutterアプリケーションをElectronと組み合わせる
さて本題です。
やる事自体はFlutterアプリケーションは素直にFlutter on the Webとして開発し、ビルド成果物を組み込むElectronライブラリを用意する形です。作成したmyappフォルダと同じ階層にElectron部分を用意するフォルダを作成します、名前はnodejs
フォルダにしておきます。
project |
nodejs
フォルダで諸々準備をするとElectronアプリケーションが利用できるようになります。
- 依存モジュールのインストール
- package.jsonの編集
- 必要なファイルの配置
依存モジュールのインストール
nodejs
フォルダでnpm init
コマンドを実行し、Electronを導入します。electron-builderが「Yarn is strongly recommended instead on npm」と強く訴えているので、Yarnを使って依存モジュールを導入します。
cd nodejs |
package.jsonの編集
インストールが完了したら必要なファイルやコマンドを整備します。まずはpackage.json
に下記の内容を追加します。
"main": "src/background.js", |
start
コマンドはピュアにFlutterアプリとして動かしたい場合にいちいちフォルダを移動するのが面倒なのでオマケのようなノリで追加しています。
必要なファイルの配置
追加したコマンドはElectronアプリケーションを起動、またはビルドする前にFlutterのビルドコマンドを記載したシェルを叩く、という仕組みにしています。
build.sh
は下記のような内容です。
|
Flutter on the Webにはindex.html
に記載されたbase
タグを参照してJavaScriptのモジュールが動く仕組みになっています。
<!-- |
このbaseタグはビルド時のオプションで変更できます。
Webアプリとしてビルドする時に、デプロイする先のドメインを柔軟に変更できるためのオプションです。
flutter build web --base-href "/myapp/" |
デフォルト値は/
になっています。Electronで利用する場合、base
タグの値は空文字が都合が良いのですが、オプションで空文字を指定するとエラーが起きてしまいます。
$ flutter build web --base-href "" |
仕方がないので一旦オプション無しでビルドして、sedコマンドで編集しています。
index.html
のテンプレートを変更してしまっても良いですが、Flutter側の変更は控えることでElectronとFlutterの関係性をなるべく疎結合なものに保ちたい意図があります。ともかくこれだけの変更でFlutter on the Web向けにビルドしたファイルがElectronのアセットファイルとして利用できます。
あとはpackage.json
に追加したコマンドで指定している場所(nodejs/src)にbackground.js
を配置しておきます。中身はよくあるElectron向けの起動スクリプトです。個人的にはVue.js向けのElectronプラグインが生成してくれるファイルが一番気が利いていると感じているのですが、Mac OSでのエッジケース向けの挙動などはそこから拝借しています。
const electron = require('electron'); |
パスはElectronをVue.jsと組み合わせた場合一般的にここになる、という意図でsrcに配置しています、名前がmain.js
になってもpackage.json
に記載した内容と齟齬がなければ問題なく動きます。
Flutter on the Web向けのファイルをビルドするとmain.dart.js
というファイルが生成されますが、今後アップデートによる挙動の変化があってもFlutter側の成果物と名称がぶつからない名前にしておくと良いでしょう。background.js
という名称もVue.js向けプラグインが生成するファイルに倣っています。
上記の準備を終えるとElectronアプリケーションとしてFlutterのデモアプリが動きます。
cd nodejs |
Flutter on Desktopとして起動したものと比較すると、微妙にフォントが変わるなどの違いが発生しますが、どちらも快適に動作します(右がFlutter on Desktopです)。ウィンドウのリサイズ時の挙動などはFlutter on Desktopの方がスムーズです、この辺りは仕組み上仕方がないかな、といった印象です。
今回の仕組みではFlutterアプリケーション自体は素直にFlutterアプリケーションとして開発できているので、Flutter on Desktopでも問題なければフットワーク軽めに移行できます。
デスクトップ対応は魅力的だけど、欲しい機能がまだ動かなかったので見送る、というパターンの時の選択肢としてはオススメできるかなと思います。
まとめ
- Flutter on Desktop未対応のパッケージはまだ存在する
- Flutter on the WebとElectronの組み合わせは簡単に実現できる
なかなかトリッキーな試みでブログ記事にするか迷いましたが、面白いという意見をいただけたのと意外と需要があるかも…?ということで記事にしてみました。