本記事は2022/1/8開催『piyopiyo.ex#3:LiveViewでポートフォリオを作ろう』の手順をまとめたものです。
見てほしいポイント
- html/cssで構成した静的WebサイトをPhoenixアプリのビューに組み込む
- daisyUI、Tailwind CSSの便利さ
- Gigalixirへのデプロイ
この手順内では、それほどLiveViewを使っていませんが、文末でLiveViewの練習コラムを紹介しますので、LiveViewをはそちらをご参考ください。
Elixir/Phoenixの環境が未だ出来ていない方は、下記いずれかのコラムを先に行っておいてください。
それではやっていきましょう。
手順を検証した筆者の環境
$ mix phx.new --version
Phoenix installer v1.6.5
$ elixir --version
Erlang/OTP 24 [erts-12.1.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace]
Elixir 1.12.3 (compiled with Erlang/OTP 24)
1.Phoenixアプリ作成〜LiveView1枚ページ追加
1-1.DB無しのプロジェクト作成
今回はDBを使用しないので--no-ecto
オプションを指定してPhoenixアプリを作成します。
$ mix phx.new piyopiyoex3_sample_portfolio --no-ecto
* creating piyopiyoex3_sample_portfolio/config/config.exs
* creating piyopiyoex3_sample_portfolio/config/dev.exs
* creating piyopiyoex3_sample_portfolio/config/prod.exs
〜略〜
Fetch and install dependencies? [Yn] Y ←依存関連のインストールを実施
* running mix deps.get
* running mix deps.compile
作成が完了すると、下記のようなメッセージが表示されます。
We are almost there! The following steps are missing:
$ cd piyopiyoex3_sample_portfolio
Start your Phoenix app with:
$ mix phx.server
You can also run your app inside IEx (Interactive Elixir) as:
$ iex -S mix phx.server
メッセージ通りにディレクトリを移動、mix phx.server
でアプリを起動し、
http://localhost:4000
にブラウザでアクセス、プロジェクトが起動できるのを確認します。
1-2.LiveViewページ追加
DBスキーマ設定なしのLiveViewページを追加します。
$ mix phx.gen.live Portfolios Portfolio portfolios --no-context --no-schema
* creating lib/piyopiyoex3_sample_portfolio_web/live/portfolio_live/show.ex
* creating lib/piyopiyoex3_sample_portfolio_web/live/portfolio_live/index.ex
* creating lib/piyopiyoex3_sample_portfolio_web/live/portfolio_live/form_component.ex
* creating lib/piyopiyoex3_sample_portfolio_web/live/portfolio_live/form_component.html.heex
* creating lib/piyopiyoex3_sample_portfolio_web/live/portfolio_live/index.html.heex
* creating lib/piyopiyoex3_sample_portfolio_web/live/portfolio_live/show.html.heex
* creating test/piyopiyoex3_sample_portfolio_web/live/portfolio_live_test.exs
* creating lib/piyopiyoex3_sample_portfolio_web/live/live_helpers.ex
* injecting lib/piyopiyoex3_sample_portfolio_web.ex
Add the live routes to your browser scope in lib/piyopiyoex3_sample_portfolio_web/router.ex:
live "/portfolios", PortfolioLive.Index, :index
live "/portfolios/new", PortfolioLive.Index, :new
live "/portfolios/:id/edit", PortfolioLive.Index, :edit
live "/portfolios/:id", PortfolioLive.Show, :show
live "/portfolios/:id/show/edit", PortfolioLive.Show, :edit
localhost:4000ではこの時点でエラーが発生します。<参照するDBが無いので!
なので、DB参照しているファイルで使わないものを削除、適宜書き換えをします。
1-2-a.使わないファイル削除、コード書き換え
$ tree lib/piyopiyoex3_sample_portfolio_web/live
lib/piyopiyoex3_sample_portfolio_web/live
├── live_helpers.ex
└── portfolio_live
├── form_component.ex ←削除
├── form_component.html.heex ←削除
├── index.ex
├── index.html.heex
├── show.ex ←削除
└── show.html.heex ←削除
lib/piyopiyoex3_sample_portfolio_web/live/portfolio_live/index.exを書き換えます。
defmodule Piyopiyoex3SamplePortfolioWeb.PortfolioLive.Index do
use Piyopiyoex3SamplePortfolioWeb, :live_view
# 下記2行は削除
#alias Piyopiyoex3SamplePortfolio.Portfolios # ←コメントアウト
#alias Piyopiyoex3SamplePortfolio.Portfolios.Portfolio # ←コメントアウト
def mount(_params, _session, socket) do
# {:ok, assign(socket, :portfolios, list_portfolios())}
{:ok, socket} # ←書き換え
end
# ↓コメントアウト
# defp apply_action(socket, :edit, %{"id" => id}) do
# socket
# |> assign(:page_title, "Edit Portfolio")
# |> assign(:portfolios, Portfolios.get_portfolio!(id))
# end
# ↓コメントアウト
# defp apply_action(socket, :new, _params) do
# socket
# |> assign(:page_title, "New Portfolio")
# |> assign(:portfolios, %Portfolio{})
# end
defp apply_action(socket, :index, _params) do
socket
|> assign(:page_title, "Listing Portfolios")
#|> assign(:portfolio, nil) # ←コメントアウト
end
…
lib/piyopiyoex3_sample_portfolio_web/live/portfolio_live/index.html.heexは1行目以降を削除(DB参照、new、edit、deleteを使わないので)
<h1>Listing Portfolios</h1>
(上記h1以外の以下は全て消す)
<%= if @live_action in [:new, :edit] do %>
<.modal return_to={Routes.portfolio_index_path(@socket, :index)}>
…
これでエラーが消えたと思います。
1-2-b. ルーター設定の追記
lib/piyopiyoex3_sample_portfolio_web/router.exに作成したページのルーター設定を追記します。
defmodule Piyopiyoex3SamplePortfolioWeb.Router do
use Piyopiyoex3SamplePortfolioWeb, :router
…
scope "/", Piyopiyoex3SamplePortfolioWeb do
pipe_through :browser
get "/", PageController, :index
live "/portfolios", PortfolioLive.Index, :index # ←追記
end
…
ここまでファイルの編集が多くて詰まった方もいるかと思います。
こちらを参照してください。
https://github.com/kn339264/piyopiyoex3_sample_portfolio/commit/f7a1f004c6cec8c3c3f0769ff19101e2b0e14f89
これで http://localhost:4000/portfolios
で表示ができるようになりました。
1-2-c. ルートディレクトリ(/)で表示させる
/直下でポートフォリオページを表示できるよう、lib/piyopiyoex3_sample_portfolio_web/router.exを書き換えます。
defmodule Piyopiyoex3SamplePortfolioWeb.Router do
use Piyopiyoex3SamplePortfolioWeb, :router
…
scope "/", Piyopiyoex3SamplePortfolioWeb do
pipe_through :browser
#get "/", PageController, :index # ←コメントアウト
live "/", PortfolioLive.Index, :index # ←変更
end
…
これでhttp://localhost:4000/
で表示できるようになりました。
2. 静的Webページのデザイン埋め込み
作成するサンプル(ポートフォリオサイト)は、下記のようになります。
https://kn339264.github.io/piyopiyo3_sample_portfolio_html/
CSSと画像を新たに作成し、各種.heexテンプレートに埋め込むことで構築していきます。
Githubはこちら。
https://github.com/kn339264/piyopiyo3_sample_portfolio_html
ポートフォリオは、daisyUI、Tailwind CSSを使ってレイアウトしています。
Tailwind CSSはCSSフレームワーク、daisyUIはTailwind CSS専用のUIコンポーネント集です。
cssファイルを見てもらうと分かるのですが、ヘッダー画像の表示以外はほぼcssを書いていません。
この程度であればdaisyUIとTailwind CSSでも書けるので便利ですね。
2-1. CSS/画像作成、.heexテンプレートの書き換え
行うことは、下記リストの通りですが、サンプルポートフォリオをそこそこ真面目に作ったらやることが多くなってしまいました。
- Tailwind CSSとdaisyUIのインストール
- ポートフォリオ用cssファイル新規作成(assets/css/portfolio.css)
- app.cssでportfolio.cssをimport(assets/css/app.css)
- ヘッダーまでの内容を変更(lib/piyopiyoex3_sample_portfolio_web/templates/layout/root.html.heex)
- mainタグの修正(lib/piyopiyoex3_sample_portfolio_web/templates/layout/live.html.heex)
- メインコンテンツを記載(lib/piyopiyoex3_sample_portfolio_web/live/portfolio_live/index.html.heex)
- 画像ファイルを設置(priv/static/images/配下)
ですので、編集対象のファイルを把握したら、githubのcommitの下記差分をそのままコピーしていただいて、次の手順(デプロイ)へ進んでほしいです。
https://github.com/kn339264/piyopiyoex3_sample_portfolio/commit/c3eb4a2729280f08a51979721cb6f29277e3c6ed
分からない場合や、上手くいかない場合は、下記リポジトリをgit clone(上記で同名のフォルダができているので、いったんリネームした後)し、mix deps.get
し、iex -S mix phx.server
してください。
なおTailwind CSSとdaisyUIは、CDNでインストールすることで、気軽に済ませています
<!DOCTYPE html>
<html lang="ja">
…
<script defer phx-track-static type="text/javascript" src={Routes.static_path(@conn, "/assets/app.js")}></script>
<!-- 下記、CDNでTailwind CSSとdaisyUIをインストール -->
<link href="https://cdn.jsdelivr.net/npm/daisyui@1.16.4/dist/full.css" rel="stylesheet" type="text/css" />
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2/dist/tailwind.min.css" rel="stylesheet" type="text/css" />
…
これでhttp://localhost:4000
の内容が書き換わりました。
3. gigalixirへデプロイしよう
ポートフォリオは公開してなんぼなので、gigalixirへデプロイしましょう。
3-1. gigalixirアカウント作成、gigalixir CLIインストール
Elixir/PhoenixをサポートしているPaaSのGigalixirを使います。
3-1-a. アカウントの登録
アカウントが無い方は登録しましょう。
無料で登録でき、有料プランを利用したい場合はログイン後のアカウントページでのアップグレード操作が必要です。
3-1-b. gigalixir CLIのインストール
Gigalixir環境へのデプロイにはgigalixir CLIを使います。
公式doc通りにgigalixir CLIをインストールしましょう。
インストールできたらターミナルからgigalixirへログインしてみましょう。
$ gigalixir login
ログインしているアカウント情報の確認。
$ gigalixir account
3-2. gigalixirアプリ作成
gigalixirアプリ(これからデプロイする環境)を作成します。
$ cd piyopiyoex3_sample_portfolio/
$ gigalixir create
アプリの情報はgigalixir apps
コマンドで確認できます。
また、gitのリモートリポジトリにgigalixirが追加されます。
$ gigalixir apps
[
{
"cloud": "gcp",
"region": "v2018-us-central1",
"replicas": 0,
"size": 0.3,
"stack": "gigalixir-20",
"unique_name": "dismal-awesome-wolverine",
"version": 2
}
]
$ gigalixir git:remote 【上記unique_nameを入力、この例ではdismal-awesome-wolverine】
$ git remote -v
3-3. Gitでバージョン管理をする
Phoenixアプリのディレクトリに移動し、空のGitリポジトリを作成します。
$ cd piyopiyoex3_sample_portfolio/
※git cloneしてない方はgit initを実行してください。
$ git init
作成したアプリのファイルをインデックスに追加、変更したファイルをリポジトリに反映します。
$ git add -A
$ git commit -m "Initialize repository"
3-4. 本番環境設定追記
3-4-a. 何もせずにデプロイしてみる
$ git push gigalixir main
本番環境用のエラーログが出るはずです。
$ git push gigalixir main
Enumerating objects: 115, done.
Counting objects: 100% (115/115), done.
〜〜略〜〜
-----> Checking Erlang and Elixir versions
Sorry, an elixir_buildpack.config is required. Please see https://github.com/HashNuke/heroku-buildpack-elixir#configuration
remote: 2022/01/07 15:06:06 exit status 1
remote: Deploy aborted
To https://git.gigalixir.com/lazy-trim-kitten.git/
! [remote rejected] main -> main (pre-receive hook declined)
ではデプロイ用の設定をしていきましょう。
3-4-b. Gigalixirデプロイ用設定を追加
Elixir、Erlang、Node.jsのバージョンがGigalixirのデフォルトのビルドパックだと古いので、開発環境とバージョンを合わせます。(ご自分の環境のバージョンに合わせて適宜書き換えてください。)
echo "elixir_version=1.12.3" > elixir_buildpack.config
echo "erlang_version=24.0" >> elixir_buildpack.config
echo "node_version=14.17.6" > phoenix_static_buildpack.config
次に、Phoenix1.6.0以降に対応されたesbuildのビルド設定を追加します。
assets/package.jsonファイルがなければ新規作成します。
{
"scripts": {
"deploy": "cd .. && mix assets.deploy && rm -f _build/esbuild*"
}
}
コミットするのを忘れないようにしましょう。
git add elixir_buildpack.config phoenix_static_buildpack.config assets/package.json
git commit -m "set elixir, erlang, and node version"
3-4-c. 本番環境設定の書き換え
本番環境のPhoenixアプリのエンドポイントの設定を追記します。
config :piyopiyoex3_sample_portfolio, Piyopiyoex3SamplePortfolioWeb.Endpoint, cache_static_manifest: "priv/static/cache_manifest.json"
# ↓ 書き換える
config :sample_portfolio, SamplePortfolioWeb.Endpoint,
url: [host: "{アプリのunique_name}.gigalixirapp.com"],
check_origin: ["//{アプリのunique_name}.gigalixirapp.com"],
cache_static_manifest: "priv/static/cache_manifest.json"
アプリのunique_nameはgigalixir apps
で確認できます。
こちらも変更内容をコミットしましょう。
$ git add config/prod.exs
$ git commit -m "add prod endpoint"
3-4-d. 再度デプロイ
$ git push gigalixir main
下記コマンドで、アプリのステータスがHealthy
になるまで待ちましょう。
$ gigalixir ps
なお、デプロイ中にエラーが出る場合は、下記をお試しください
$ git push -f gigalixir main
Gigalixirで稼働しているアプリを表示します。
反映されるまで数分かかることがあるので、まったり待ちましょう。
$ gigalixir open
表示できたらデプロイおわりです、おめでとうございます!
※デプロイ設定のコードはこちらです。
https://github.com/kn339264/piyopiyoex3_sample_portfolio/tree/deploy_gigalixir
最後に
当日の勉強会では1時間弱でここまで書いた内容を進行する予定ですが、時間的にボリュームが多すぎるなと思いながら記事を書いています。
参加者の皆様おつかれさまでした!
参考:LiveViewの練習コラムのご紹介
- LiveViewでCRUD操作するDB操作ページ群を生成(Scaffold)
- LiveViewでグラフィック操作
- LiveViewでQiita記事をリアルタイム検索するSPAを開発
- LiveView CRUDのAPI化