こんにちは!
プログラミング未経験文系出身、Elixirの国に迷い込んだ?!見習いアルケミストのaliceと申します。
今回はElixirDesktop Phoenix1.7のアプリをWindows11 + WSL2で動かす手順をまとめなおします。
目的
Phonenix+LiveViewでCRUD機能のあるアプリを実装してエミュレータやスマホ実機で動かしたい。
実行環境
android-example-appを動かす環境とElixir, Erlangのバージョンが違います。ご注意ください。1
Windows 11 + WSL2 + Ubuntu 22.04
Elixir v1.15.7-otp-26
Erlang v26.1.2
Phoenix v1.7.3
今回やりたいこと
Phoenix1.7をElixirDesktopの環境で動かしたい。
まずはデスクトップ(PC)での動作確認をしたい。
前提条件
Elixirのインストール
以下のいずれかが未実施の場合は前回の記事を参照して環境構築を行ってください。
- Android Studioのインストール
- NDK(※Native Development Kitの略、Android で C や C++ のコードを使用できるようにするツールセット)のインストール
- git、npm、asdf のインストール
asdfを使用してのErlangおよびElixirのインストールおよび設定
インストール
asdf install erlang 26.1.2
asdf install elixir 1.15.7-otp-26
環境変数に設定-グローバル変数
asdf global erlang 26.1.2
asdf global elixir 1.15.7-otp-26
(余談)環境変数に設定-ローカル変数
ローカル変数に入れるとそのディレクトリ配下でのみ適用されます。
グローバル変数に入れるかローカル変数に入れるかはお好みで。
asdf local erlang 26.1.2
asdf local elixir 1.15.7-otp-26
Phoenixのインストール
最新のPhoenixをインストールします。
(私は既にインストール済のためスキップしました)
mix archive.install hex phx_new
SQLite3のインストール
apt経由でSQLite3をインストールします。2
sudo apt install sqlite3
rootプロジェクトの作成
まず、Phoenixのプロジェクトとandroid-studioのプロジェクトの2つが必要なので、両方のプロジェクトをいれるディレクトリを作成します。
mkdir todo_root
cd todo_root
Phoenixプロジェクトの作成
次に、Phoenixのプロジェクトを作ります。
DBはsqlite3を使うので --database sqlite3のオプションをつけます。
mix phx.new todo_app --database sqlite3
cd todo_app
mix ecto.create #todo_app_dev.dbが作成される
ライブラリの追加
defp deps do
[
...
+ {:exqlite, github: "elixir-desktop/exqlite", override: true},
+ {:desktop, "~> 1.5"},
+ {:wx, "~> 1.1", hex: :bridge, targets: [:android, :ios]}
]
end
- exqliteとは、ElixirDesktopからSqlite3を操作するライブラリ
- desktopとは、ElixirDesktopフレームワーク本体
- wxとは、ElixirDesktopをスマートフォン上で動かすためのライブラリ
追加後、以下を実行します。
mix deps.get
config修正
config :todo_app, TodoAppWeb.Endpoint,
- url: [host: "localhost"],
+ http: [ip: {127, 0, 0, 1}, port: 10_000 + :rand.uniform(45_000)],
render_errors: [
formats: [html: TodoAppWeb.ErrorHTML, json: TodoAppWeb.ErrorJSON],
layout: false
],
pubsub_server: TodoApp.PubSub,
- live_view: [signing_salt: "J82JhPeQ"]
+ live_view: [signing_salt: "J82JhPeQ"],
+ secret_key_base: :crypto.strong_rand_bytes(32),
+ server: true
※signing_saltの値は人によって異なります。
- secret_key_baseとは、secureな文字列を作る際のベースになるもの。
- server: trueとは、アプリケーションが起動しているサーバーのIPアドレス + ポート番号への外部からのアクセスを受け付けられるようになる設定。3
runtime.exsの無効化
アプリの実行時にtodo_app/config/runtime.exs
があるとエラーになるそうです。
よって、runtime_disable.exs
にリネームしておきます。
Endpoint設定
EndpointのモジュールをPhoenixからDesktopに変更します。
ElixirDesktopではcookieでのセッション管理を使えないのでetsに変更します。
defmodule TodoAppWeb.Endpoint do
- use Phoenix.Endpoint, otp_app: :todo_app
+ use Desktop.Endpoint, otp_app: :todo_app
@session_options [
- store: :cookie,
+ store: :ets,
key: "_todo_app_key",
- signing_salt: "GvxD48aX",
- same_site: "Lax"
+ table: :session
]
アプリケーション起動時の設定
todo_app.ex
にどのような手順でPhoenixアプリケーションを起動していくかの設定をします。
todo_app.ex
にはデフォルトではドキュメントしか書かれていないので、以下を追加します。
defmodule TodoApp do
+ use Application
+ def config_dir() do
+ Path.join([Desktop.OS.home(), ".config", "todo_app"])
+ end
+ @app Mix.Project.config()[:app]
+ def start(:normal, []) do
+ # ~/.config/todo_appフォルダを作成する。その中に設定ファイルを放り込んでいく
+ File.mkdir_p!(config_dir())
+ # DBの場所を指定
+ Application.put_env(:todo_app, TodoApp.Repo,
+ database: Path.join(config_dir(), "/database.sq3")
+ )
+ # session用のETS(インメモリDB)を起動
+ :session = :ets.new(:session, [:named_table, :public, read_concurrency: true])
+ children = [
+ TodoApp.Repo,
+ {Phoenix.PubSub, name: TodoApp.PubSub},
+ TodoAppWeb.Endpoint
+ ]
+ opts = [strategy: :one_for_one, name: TodoApp.Supervisor]
+ # Phoenixのsuperviserをメインとして起動
+ {:ok, sup} = Supervisor.start_link(children, opts)
+ # DBの初期化とマイグレーション実行
+ TodoApp.Repo.initialize()
+ # phoenixサーバーが起動中のポート番号を取得
+ port = :ranch.get_port(TodoAppWeb.Endpoint.HTTP)
+ # ElixirDesktopのsuperviserを子プロセスとして起動
+ {:ok, _} =
+ Supervisor.start_child(sup, {
+ Desktop.Window,
+ [
+ app: @app,
+ id: TodoAppWindow,
+ title: "TodoApp",
+ size: {400, 800},
+ url: "http://localhost:#{port}"
+ ]
+ })
+ end
+ def config_change(changed, _new, removed) do
+ TodoAppWeb.Endpoint.config_change(changed, removed)
+ :ok
+ end
end
-
Desktop.OS.home()
はユーザーのホームディレクトリを返す関数4 - superviserとは、アプリが落ちたときに自動的にプロセスキルして再起動してくれるもの。堅牢なシステムを作る際に有用。
repo.exの変更
todo_app.ex
から呼び出される関数の設定をします。
(ひとまず空の関数を置いておきます)
defmodule TodoApp.Repo do
...
+ def initialize() do
+ end
end
mix.exsの変更
mix.exs
で呼び出される起動時の設定を変更します。
# アプリケーション起動時の設定 で設定したtodo_app.ex
に差し替えます。
def application do
[
- mod: {TodoApp.Application, []},
+ mod: {TodoApp, []},
extra_applications: [:logger, :runtime_tools]
]
end
以上がPhonenixプロジェクトの設定です。
iex -S mixでデスクトップ上での起動を確認
iex -S mix
localhost:4000番ポートでデスクトップアプリの起動が確認できました(^▽^)/
※あとはこれがモバイルアプリとしてスマホで見ることができればPhoenix1.7のアプリが起動できたと言い切れます。
~Elixirの国のご案内~
↓Elixirって何ぞや?と思ったらこちらもどぞ。Elixirは先端のアレコレをだいたい全部できちゃいます
↓ゼロからElixirを始めるなら「エリクサーチ」がおすすめ!私もエンジニア未経験から学習中です。
↓We Are The Alchemists, my friends!5
Elixirコミュニティは本当に優しくて温かい人たちばかり!
私が挫折せずにいられるのもこの恵まれた環境のおかげです。
まずは気軽にコミュニティを訪れてみてください。6
-
前回の記事はandroid-example-appを動かす環境構築を目的としており、android-example-appのREADMEにてElixir, Erlangをバージョン指定されていたためそちらに合わせていました。 ↩
-
sqlite3の導入。参考にさせていただきました。 https://qiita.com/t-yamanashi/items/ef4c5bcab4a130105760 ↩
-
外部とはローカルホスト(同一マシン)以外を指す。 ↩
-
https://github.com/elixir-desktop/desktop/blob/5927dc42d97305c43cad523b905153b687434219/lib/desktop/os.ex#L21 ↩
-
@torifukukaiouさんのAwesomeな名言をお借りしました。Elixirコミュニティを一言で表すと、これに尽きます。 ↩