やってみよう!Phoenix Live View その①

webアプリ開発
目次

Phoenix Live Viewを始めよう

LiveView プロセス、エントリーポイント、関数コンポーネントなどの基礎的な概念に親しんで行きましょう。

本章では次のような仕様を追加します。

  • 画面の上部に「Home」と「Robot」という 2 つのリンクが表示される。
  • ユーザーが「Robot」をクリックすると、枠線の中に「Robot」と表示される。

シングルページアプリケーション(SPA)とは?

伝統的なウェブアプリケーションでは、繰り返し新たなページをロードすることで様々な機能が実現されています。それに対して、シングルページアプリケーションでは最初にロードされたページを JavaScript の力を借りて次々と書き換えていきます。

JavaScript によるページの書き換えは新たなページをロードするよりも時間がかからないので、シングルページアプリケーションはネイティブアプリケーションのようなユーザー体験を提供します。

AjaxとWebSocket

シングルページアプリケーションを実現するための主な技術要素は、次の 2 つです:

  • Ajax(エイジャックス)
  • WebSocket(ウェブソケット)

Ajax は、JavaScript の組み込みクラスである XMLHttpRequest を利用して、ブラウザからサーバーに対して HTTP リクエストを送ってデータを取得することにより、ページを動的に書き換えるという開発手法です。

WebSocket は、ブラウザとサーバーの間で双方向通信を実現するための通信プロトコルです。サーバー側からブラウザにデータをプッシュ配信することが難しいという Ajax の欠点を解決するための技術として開発されました。

Phoenix LIve View

Phoenix LiveView は WebSocket を利用してシングルページアプリケーションを開発するためのライブラリです。Phoenix とは独立したライブラリですが、--no-liveview オプションを付けずに mix phx.new コマンドを実行すると Phoenix LiveView が Phoenix アプリケーションに組み込まれます。

LiveViewモジュール

RobotLiveモジュールを作る

コントローラのためのモジュールの場合は、HomeController のように「Controller」で終わる名前のモジュールを作りましたが、Phoenix LiveView のためのモジュールの場合は、「Live」で終わる名前とするのが慣習です。この種のモジュールを LiveView モジュールと呼びます。

モジュールのソースコードを置くためのディレクトリを作ってください。

mkdir -p lib/phx_sample_web/live

そして、その下に新規ファイル robot_live.ex を作り、次のコードを書き入れてください。

defmodule PhxSampleWeb.RobotLive do
  use PhxSampleWeb, :live_view
end

LiveView モジュールの場合は、use PhxSampleWeb, :live_view のように書きます。

メインテンプレートを作る

次に、同じディレクトリに robot_live.html.heex を次の内容で作ってください。

<div>Robot</div>

RobotLive モジュールのメインテンプレートとして使われます。最初は単に「Robot」と表示するだけとします。

ルーティング設定の変更

ルーティング設定を次のように変更します。

scope "/", PhxSampleWeb do
   pipe_through :browser

   get "/", HomeController, :index
   get "/", HomeController, :hello
   get "/hello/:name", HomeController, :hello

  live "/robot", RobotLive
 end
end

この結果、ブラウザで /robot パスにアクセスしたときに RobotLive モジュールが応答します。

ナビゲーションバーの設置

app レイアウトapp.html.heexの上部にナビゲーションバーを設置しましょう。

<header class="flex justify-center">
  <a href={~p(/)} class="link mx-2">Home</a>
  <a href={~p(/robot)} class="link mx-2">Robot</a>
</header>
<main class="px-4 py-20 sm:px-6 lg:px-8">
  <div class="mx-auto max-w-2xl sm:border-4 sm:border-base-content sm:p-4">
    <.flash_group flash={@flash} />
    {@inner_content}
  </div>
</main>

まだ機能を何も追加していないので見た目からはわかりませんが、シングルページアプリケーションとして機能し始めており、ブラウザと Phoenix サーバーの間は WebSocket で接続しています。

WebSocket通信の状態を確認する方法

本当に WebSocket 通信が成立しているかどうかは、ブラウザの DevTools を使って確認できます。Chrome の場合は、ページ内を右クリックしてコンテキストメニューを開き、「検証」を選択すると DevTools が開きます。

「Network」タブを選択し、「All」、「Fetch/XHR」などのボタンが並ぶ中から「Socket」ボタンをクリックし、ブラウザの画面をリロードすると DevTools には次のように表示されます。

画面下半分の表に websocket? で始まる行が 2 つありますね。これらの行が存在すれば、WebSocket 通信が成立しています。

2 つの行のうち websocket?_csrf_token= で始まっている方を選択してください。すると次のような表示に変化します。


上向きの矢印がブラウザからサーバーに向けての通信、下向きの矢印がサーバからブラウザ向きの通信を示します。「Len...」の列には送信されたデータのサイズ(単位:バイト)が書かれています。最初にブラウザから 863 バイトのデータが送られ、サーバーから 8841 バイトのデータが返ってきていることがわかります。

「Time」列には通信が行われた時刻が書かれています。ここを見ると、30秒ごとにブラウザとサーバーの間でごく小さなデータのやり取りが発生していることがわかります。このときにブラウザからサーバーに送られるデータをハートビートと呼びます。これが途絶えると、サーバー側は WebSocket 通信が切断されたと判断します。