はじめに
この記事は「Elixir Advent Calendar 2022」vol1 20日目の記事です.
ElixirConf 2022 USで発表されたLiveView Nativeの解説します
LiveViewNativeとは
Phoenix LiveViewを共通プロトコルとしたマルチプラットフォーム
LiveView Nativeは、Phoenixを使用してネイティブアプリケーションとWebアプリケーションをシームレスに構築できるようにするものです。
複数のチームを管理したり、複数のフレームワークを使いこなす必要はありません。
同じ開発者が両方を管理することで、納期を短縮し、イノベーションに集中するためのリソースを確保できます。
LiveView Nativeの特徴
LiveView Nativeを使用することで、単一のチームがWebおよびネイティブアプリケーションのフロントエンド開発を実行し、Phoenixのサーバーサイドレンダリングの利点を活用することが可能になりました。ElixirがWebにもたらす多くの利点を、今度はネイティブ環境で実感してください。
- 複雑なクライアントサイドのアプリケーションを、重いJavaScriptフレームワークで構築するよりも高速かつ軽量に構築できます。
- あらゆるプラットフォームでより良いユーザー体験を提供(「不気味の谷」現象はもう起きない)
- Webとネイティブにまたがる単一のコードベースを管理する単一チームによる生産性とリソースの最適化
ElixirConf USざっくり
- Phoenix LiveViewをプロトコルとしたネイティブプラットフォーム実装
- バックエンドにPhoenixをそのまま使う
- フロント部分を各ネイティブ環境用のDSLで記述し、クライアント側で解析して画面を組み立てる
- ElixirConf USでLiveViewNativeで実装されたiOS製のチャットアプリをリリースして実際にイベントの交流ツールとして使用した
-> すでにプロダクションで使われている
LiveViewNativeとElixirDesktopの違い
LiveViewNative | ElixirDesktop |
---|---|
ネイティブUIで表示 | WebViewで表示 |
外部Phoenixサーバー | 内部Phoenixサーバー |
ネイティブ機能と連携容易 | WebViewを通してネイティブ機能を使用 |
個々のネイティブUIの知識が必要 | Webアプリの知識で実装可能 |
LiveViewNative アーキテクチャざっくり
- Swift側から LiveViewCoordinatorで接続先を指定
- Phoenix側で index.ios.heexというSwiftUIのコンポーネントのDSLで書いたLiveViewページを表示
- liveview-client-swifuiでそのデータを元に画面をビルドする
Swift側でやること
- PhoenixLiveViewNativeを読み込む
- LiveViewCoordinatorを作成
- ナビゲーション等の設定
- PhoenixサーバーのURLをセット
- ContentViewで LiveViewを表示
実際のコード
import SwiftUI
import PhoenixLiveViewNative
struct ContentView: View {
@State var coordinator: LiveViewCoordinator<MyRegistry> = {
var config = LiveViewConfiguration()
config.navigationMode = .enabled
return LiveViewCoordinator(
URL(string: "http://localhost:4000/cats")!,
config: config
)
}()
var body: some View {
LiveView(coordinator: coordinator)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Phoenix側でやること
- URLに対応した.ios.heexをつくる
- DSLでviewを記述
- ページ単位ではなくアプリ全体でstateを管理するGenServerの作成(なくても作れる)
defmodule LvnTutorialWeb.CatLive do
use LvnTutorialWeb, :live_view
require EEx
alias LvnTutorial.FavoritesStore
EEx.function_from_file(
:def,
:render,
"lib/lvn_tutorial_web/live/cat_live.ios.heex",
[:assigns],
engine: Phoenix.LiveView.HTMLEngine
)
def mount(%{"name" => name}, _sesion, socket) do
{:ok,
assign(socket,
name: name,
favorite: Enum.member?(FavoritesStore.get_favorites(), name),
score: FavoritesStore.get_score(name)
)}
end
...
end
EEx.function_from_fileでの設定はライブラリを開発中なのでもう少し簡単になると思います
<list navigation-title="Cats!">
<%= for {name, favorite} <- @cats_and_favorites do %>
<navigationlink
id={name}
data-phx-link="redirect"
data-phx-link-state="push"
data-phx-href={Routes.live_path(@socket, LvnTutorialWeb.CatLive, name)}
>
<hstack id={name}>
<asyncimage src={"/images/phoenix.png"} frame='{"width": 100, "height": 100}' />
<text><%= name %></text>
<spacer />
<button phx-click="toggle-favorite" phx-value-name={name}>
<image system-name={if favorite, do: "star.fill", else: "star"} symbol-color={if favorite, do: "#f3c51a", else: "#000000"} />
</button>
</hstack>
</navigationlink>
<% end %>
</list>
Swift側でできること
- coordinator.pushEventでPhoenix側のイベントを発火
-> センサデータや写真などをPhoenix側に送信するのが容易 - カスタムコンポーネントを作成してPhoenix側で使用
- iOSだけでなくmacOS, watchOS, tvOSのアプリも作れる
チュートリアルサイト
実際に試してみたい方はこちら!
ロードマップ
- SwiftUIの全コンポーネントをカバー
- Jetpack対応
- WinUI3対応
展望
iOS,Android, Windowsだけでなく、C# Channels clientを通してUnityを操作できるようにするという恐ろしい計画があるそうです
最後に
いかがでしたでしょうか
すでにiOSアプリのフロントをLiveViewのDSLで記述し、バックエンド及びステート管理をLiveViewで実装できる激アツプロダクトだと思います
今年はまだα版な感じでまだこなれてないのと、あまり時間がないので触れてないですが
来年はこれを使ってアプリを実際に作りたいと思います
本記事は以上になりますありがとうございました
参考サイト
https://speakerdeck.com/thehaigo/elixirconfxi-garideliveviewnativeyatutemita
https://liveviewnative.github.io/liveview-client-swiftui/tutorials/yourfirstapp/
https://github.com/liveviewnative/liveview-client-swiftui
https://www.youtube.com/watch?v=dnDGh_Jmw-s