iOS,AndroidでWebアプリケーションを動かすスマホアプリをElixirで作った話

# はじめに
開発でチャレンジして、失敗・成功したことをシェアしよう by 転職ドラフト Advent Calendar 2024のシリーズ２、４日目の記事です

https://qiita.com/advent-calendar/2024/engineering-careers-1

iOS,AndroidでWebアプリケーションを動かすスマホアプリをElixirで作った話を以下の内容で解説していきます

- リリースしたアプリ
- アーキテクチャ
- 使用した技術
- 苦労した点

# リリースしたアプリ

旅行プランの組み立て、GPSロギングを行う旅行記アプリ TrarecoをApp Store、Google Play Storeでリリースしています

このアプリは以下の機能を実装しています
- 行ってみたい所を素早く、検索・登録
- 登録した場所を他の地図アプリで開いてナビゲーション
- 登録した場所を使って旅行プランの組み立て
- アプリ内の地図でGPSロギングと旅行プランへのチェックイン

![スクリーンショット 2024-11-22 15.50.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/3e6bb7f7-5a08-2d45-b9ab-f4618fb2081f.png)

https://apps.apple.com/jp/app/trareco/id6499554525

https://play.google.com/store/apps/details?id=com.trareco


# アーキテクチャ
このアプリを実現するのにElixirDesktopというライブラリを使用しています
詳細については使用する技術で解説します

## ElixirDesktopを使用したアプリのアーキテクチャ

`ElixirDesktop`は各OSのXcodeやAndroidStudio等で開発する、ネイティブなアプリケーション上で`Erlang`及び`Elixir`を起動させ、Webアプリケーションサーバーである`Phoenix`を動かします。

それを各OSの`WebView`やGUIライブラリの`WxWidget`からアクセスして表示する`WebView`アプリケーションの形式を取っています。

通常のWebViewアプリの違いとしては、通常はクライアントアプリケーションとWebサーバーとの通信を行うのですが、ElixirDesktopは同一の端末内でそれを実現します。

通常
![スクリーンショット 2024-11-02 22.52.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/18933fb1-2290-4ed8-371e-29acf74e4099.png)

ElixirDesktop
![スクリーンショット 2024-11-02 22.52.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/8d038c5f-4966-7600-8146-5ece9667210c.png)

この構成によってオフラインでの動作や、
画面のレンダリングや大きなデータの送受信などWebサーバーのリソースが節約できます。
まだ研究段階ではありますが、分散DBやDB同期を使用してDBコストの削減ができそうです


## ElixirDesktopで作れる３つのアプリ形式

ElixirDesktopでは主に３種類の構成でアプリを作れます

![スクリーンショット 2024-11-02 23.39.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/eaa3b29d-fea3-c725-9b75-d0a29c2eeaa9.png)
![スクリーンショット 2024-11-02 23.39.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/9bf19800-87f1-68d3-cc5f-9cf4a9aa2435.png)
![スクリーンショット 2024-11-02 23.40.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/fa906431-9988-0d7b-cee5-f6b652c4c5c8.png)

今回のアプリは３つめの外部のDBに直接アプリからコネクションを貼る形式を採用しています

# 使用した技術

使用した以下の技術について軽く解説します

* イミュータブルを基本とした学習曲線がゆるい関数型言語`Elixir`
* フルスタックWebアプリケーションフレームワーク`Phoenix`
* リッチなリアルタイムSPAをシンプルに構築できる`LiveView`
* マルチプラットフォームなアプリを作れる`ElixirDesktop`


## イミュータブルを基本とした学習曲線がゆるい関数型言語Elixir

`Elixir`はイミュータブルを基本とし、クラスを言語機能として持たないため、オブジェクト指向由来の複雑さを排除し、意図しないパラメーターの変更が起きにくくなります。

また`Ruby`に近い文法かつ、初学者にとって壁となりがちな静的型ではなく動的型を導入しており、他の関数型言語に比べて緩やかな学習曲線であると私は認識しています。

- イミュータブルを基本とした意図しない変更をさせない堅牢性
- 強力なパターンマッチによる、データの取捨選択とエラーハンドリング
- 関数パターンマッチによるシンプルな条件分岐
- パイプ演算子にるネストした処理の簡略化
- アクターモデルによるシンプルな分散・並列処理
- Enumモジュールによるリッチな配列処理
が特徴です

## フルスタックWebアプリケーションフレームワークPhoenix

`Phoenix`はフルスタックのWebアプリケーションフレームワークであるため、アプリケーションを作成するにあたって基本的な機能に関するライブラリの選定が必要なく、安定性が高く相性問題等も起きません。

またRailsでいうScaffolding(CRUD機能ジェネレーター）があるため、開発のスタンダードが示されており開発のキャッチアップが容易となっています

これを使用することでWebアプリケーション開発の技術スタックでモバイルアプリ開発を行えます。

- フルスタック構成
- MVCアーキテクチャ、HotWireアーキテクチャでの開発
- API,CRUD,認証機能の各種ジェネレータ
- 自動テスト、E2Eテスト
- Erlangの軽量プロセスによるハイパフォーマンス、耐障害性の高さ
が特徴です

## リッチなリアルタイムSPAをシンプルに構築できるLiveView

`Phoenix`で採用しているフロントエンドを開発するライブラリ`LiveView`は、`JavaScript`をほとんど記述することなく、`React`等を使用した従来のSPA開発と遜色ない体験を提供します。

`LiveView`は`WebSocket`を介して通信し、複雑なステート管理、大量のAPIを作成することなく、リッチなSPAの開発を行えます。

またフロントエンドを開発する際は`Heex`というテンプレートエンジンを使用し、HTMLと`Phoenix`に標準で搭載されている`Tailwind`で開発します。

また`Tailwind`が搭載されているのでUIの構築にTailwindの資産（多数のUIコンポーネント）を使え、開発省力化が可能です。

- モジュールに閉じたシンプルなState管理
- JS Hookによる双方向のインタラクション
- Tailwindによる既存のUIコンポーネントをベースにした開発
- WebSocket通信による差分レンダリング

が特徴です

これらを使用し`Phoenix`のwebアプリケーション開発の知識でモバイルアプリ、デスクトップアプリの開発ができます。


# マルチプラットフォームなアプリを作れる`ElixirDesktop`

`ElixirDesktop`とは、iOS, AndroidやmacOS, Linux, Windowsなどマルチプラットフォーム上で動作するアプリケーションを作成するElixirのライブラリ群です。

https://github.com/elixir-desktop/desktop


## メリデメ 

ElixirDesktopで開発する際に以下のメリット・デメリットがあります

### メリット

- Webサーバーのリソースをクライアント側で賄える(AI/MLも）
- 未処理の大容量ファイル送信等のデータ通信量の削減
- オフライン動作が可能
- Web系の技術で開発できる
- 構成によってはAPI不要
- ReactNative,Flutterに比べてネイティブ連携が容易

大きなメリットとしては、Web系の技術スタックで開発できるのでキャッチアップが容易で、Webの人をモバイルに回すことも容易になることがあります

### デメリット

- 秘匿情報の扱いが面倒
- Bcryptなどネイティブライブラリのラッパーライブラリが使えない
- 出来て日が浅い
  - バグが残っている可能性
  - 長期運用でのノウハウ不足


## どうやって実現しているのか

`Erlang`をクロスコンパイルし、各OS上で実行可能なスタティックライブラリを作成します。そして各OSで実装されたBridgeを通して、アプリケーション実行時に`Erlang`を起動し、その`Erlang`上で`Elixir`及び`Phoenix`を起動する。

`Phoenix`を起動後は各OSの`Webview`を通して各画面を表示します。

iOS、Androidのアーキテクチャはそれぞれ次のようになっています。

![01_04_ios_elixir.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/45d3c01c-c508-3be2-79a3-1b1136242a57.png)


https://github.com/elixir-desktop/ios-example-app?tab#readme-ov-file#architecture

![01_05_android_elixir.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/9eceeaff-d0d1-7e10-fbae-f6501fde5d1b.png)

https://github.com/elixir-desktop/android-example-app?tab#readme-ov-file#architecture


## ElixirDesktopができること

`ElixirDesktop`では`Webview`アプリのためWebでできることは大体でき、各OSのフックを利用してのネイティブ機能の実行も行えます。

具体的には次のことが可能です。

 * Webアプリケーション開発の技術スタックでのモバイル、デスクトップアプリの開発
 * `Phoenix`にデフォルトで組み込まれている`Tailwind CSS`を使用したリッチなUIの構築
 * JSライブラリ(`Google Maps`, `WebGL`)での画面描画(3D,2D)
 * `SQLite`や`DETS`などの内部DBによるオフラインでも動作可能なアプリケーションの開発
 * 外部DBに接続しAPIレスのアプリケーション開発
 * 従来の認証トークンを端末に保存して外部のAPIとの通信
 * `WKScriptMessageHandler`を使用したiOSネイティブAPIコールとコールバック
 * `WebAppInterface`を使用したAndroidネイティブAPIコールとコールバック
 * 各OS向けのインストールバイナリの生成
 * OpenCVのElixirバインディングである`Evision`による画像処理

https://github.com/cocoa-xu/evision

https://qiita.com/RyoWakabayashi/items/100617a772d8ec71adea

## ElixirDesktopができないこと

Webでできることは大抵できますが、モバイルアプリでクロスコンパイルが必要なライブラリの使用が困難です。

具体的な例として、`Google XLA`や `Facebook libtorch`を使用したAIや機械学習のモデルの高速実行を行えません。
ですがモバイルで動作可能なライブラリの開発、`Rust`を使用しての`WebAssenbly`からの実行で将来的には解消できる可能性があります。

機械学習に関しては、`IREE`のElixirバインディングの`NxIREE`や行列演算の高速化にMetalのAPIを叩く`MLX`開発が進んでおり、iOS等で使用可能になる可能性が高いです。

https://github.com/elixir-nx/nx_iree

https://github.com/elixir-nx/emlx

# ElixirDesktopの問題点

利点が多い`ElixirDesktop`ですが、いくつか問題点があります。

## 構築した環境が壊れやすい

モバイルアプリ開発に共通することですが環境構築が初学者には非常に難しいです。

`Erlang`のバージョンや依存ライブラリに加え`Xcode`、`AndroidStudio`のバージョンにの違いに非常にシビアで、構築した環境が動かなくなるということがよくおこります。

## 開発環境がMac以外だとハードルが高い

基本的に`macOS`での開発でを想定しているため`Windows`だと`Phoenix`側の開発は`VSCode`等で問題はあまりありません。ですが、`Android`のシミュレーターや実機テストを行うときには`WSL2`上の`Ubuntu`を起動させ、その上で`Linux`用の`AndroidStudio`を起動させてビルドを行う必要があり初学者にとってハードルが非常に高いです。

# 苦労した話

- 本家はサンプルしかなく、サンプルを解析して最小構成を模索した
- ランタイムのバージョンが低く、ビルドが必要だった
- 各OS向けのジェネレーターの作成


## 本家はサンプルしかなく、サンプルを解析して最小構成を模索した

https://github.com/elixir-desktop

ライブラリのページのリポジトリ一覧を見ると
iOSとAndroidのExampleとサンプル内で動かすWebアプリ、desktopとその他のユーティリティがあります

メインのライブラリとなるdesktopをみてもジェネレータの類は見当たらなかったので、サンプルを解析しながら最小構成を模索して、デスクトップアプリ化、iOSプロジェクトの作成・起動、Androidプロジェクトの作成・起動をその都度行っていました

その試行錯誤の結果、去年のアドカレでまとめることが出来ました

https://qiita.com/the_haigo/items/4a63320fe504c5dface2#%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E4%BD%9C%E6%88%90


## ランタイムのバージョンが低く、ビルドが必要だった

サンプルで使用している Erlangのランタイムのバージョンが現行の27の２つ前の25を使用していて、パフォーマンスが悪いのと現在のmacOSのバージョンでは上手くインストールが出来ない等問題があり、自身でランタイムのビルドが必要でした。

ビルド環境やスクリプトに関しては作者の方が作っていたのでなんとかなったのですが、やはり未知の領域のため結構大変でした

https://github.com/elixir-desktop/runtimes

無事ビルドが出来た過程を去年のアドカレに記事としてまとめています

https://qiita.com/the_haigo/items/9da7f1a1e91f391b6819

## 各OS向けのジェネレーターの作成

苦労した話の１つめに`サンプルを解析して最小構成を模索した`がありましたが、やはり毎回１から作るのは大変なので、ジェネレータを自作しました

仕組みもよくわからなかったので最初はどうすればよいか途方に暮れてましたが、Elixirでスマホアプリを作るために別のアプローチを採っていたLiveViewNativeに各OSのプロジェクトと既存のWebアプリケーションをアプリ化するためのジェネレータがあったので、それを参考に無事作ることが出来ました

ジェネレータ

https://github.com/thehaigo/desktop_setup

ElixirDesktopとは別アプローチのネイティブアプリのライブラリLiveViewNative

https://dockyard.com/blog/2024/09/09/liveview-native-is-here

参考にしたジェネレータのコード

https://github.com/liveview-native/live_view_native/tree/main/lib/mix

https://github.com/liveview-native/liveview-client-swiftui/tree/main/lib/mix/tasks

# まとめ

まだまだ開発途上ではありますがWebアプリの知識と技術スタックでモバイルアプリ、デスクトップアプリを開発できるというのは非常に魅力的ではありますので、皆さんぜひ使ってみてください。

興味のある方は技術書典17でだしたElixirDesktop書籍や

https://techbookfest.org/product/6CZLPU2qRByFT3rjyVSAhM?productVariantID=cKas4WAKAfPHqcUgg5hDG6

Elixirアドベントカレンダーの記事を

https://qiita.com/advent-calendar/2024/elixir

またElixirやPhoenixに興味が出た方はElixirのコミュニティで執筆した書籍がありますのでぜひそちらを読んでいただけたらと思います

https://gihyo.jp/book/2024/978-4-297-14014-4


本記事は以上になります、ありがとうございました


# 参考URL

https://github.com/elixir-desktop/desktop
https://hexdocs.pm/elixir/introduction.html
https://hexdocs.pm/phoenix/overview.html
https://hexdocs.pm/phoenix_live_view/welcome.html
https://github.com/cocoa-xu/evision
https://qiita.com/RyoWakabayashi/items/100617a772d8ec71adea
https://iree.dev/
https://github.com/elixir-nx/nx_iree
https://github.com/elixir-nx/emlx
https://github.com/thehaigo/desktop_setup
https://github.com/liveview-native/live_view_native/tree/main/lib/mix
https://github.com/liveview-native/liveview-client-swiftui/tree/main/lib/mix/tasks
https://gihyo.jp/book/2024/978-4-297-14014-4