Phoenix LiveViewで加速する開発効率──Colocated Hooks & JavaScriptの威力に迫る

technology

この記事の途中に、以下の記事の引用を含んでいます。
Phoenix LiveView Colocated Hooks and JavaScript


シンプルで強力!LiveViewにやってきた「Colocated Hooks」とは?

ElixirでリアルタイムWebアプリ開発を可能にするPhoenix LiveView。

そのバージョン1.1から追加された「colocated JavaScript Hooks(コロケーテッド・フック)」が今、開発者のワークフローを大きく進化させています。

今回の記事は、この便利機能の概要と、どのような意義を持ち、実践でどう活用できるのかを解説します。

また、プロダクションコードで具体的にどう使うかも交えつつ、私自身の技術的考察もまとめています。


驚くほど簡単に拡張!Colocated Hooksの導入ポイント

まず、元記事では、colocated hookについてこう説明されています:

“A colocated hook lives alongside your component code. This makes writing simple hooks much easier. Instead of having to create a separate file, we can just add our hook to our HEEx component.”

Phoenix LiveView Colocated Hooks and JavaScript

この一文は、LiveViewコンポーネントのHTML(HEExテンプレート)内部に、そのままJavaScriptフックのコードを直接記載できるようになった、という意味です。

従来であれば、LiveViewコンポーネントと連携するJavaScriptフック(カスタムイベントリスナーなど)は、全てassets/jsのようなディレクトリに、ファイルを分けて記述し、それをアプリ側でリンクさせる必要がありました。

しかし、「colocated hooks」導入後は、その煩雑なファイル構成を気にせず、HEExファイルに <script :type={Phoenix.LiveView.ColocatedHook}> タグを使って直接JSを書くことができるのです。

これにより、JSフックを必要とするコンポーネントと、そのJSロジックが同じ場所で管理できるようになりました。


なぜ重要?SPA+リアルタイム時代の“分離と共存”の最適解

この仕組みがなぜ画期的なのか。

ポイントは2つ挙げられます。

1. コンテキストの一元管理による開発効率の大幅向上

“Separation of concerns(関心の分離)”はソフトウェア設計の王道ですが、実はフロントエンド・バックエンドの垣根が急速に曖昧になる近年、分けたことで生じるコスト(編集時の移動や知的コンテキストの切替)も増えていました。

特にLiveViewのように「サーバ駆動UI+スポット的なJS拡張(ボタンのコピーやUIアニメーションなど)」のケースは、「ちょっとしたJS」のためだけに、巨大な構成を設計しなければなりませんでした。

Colocated Hooksはこの課題に対する答えの一つです。

今や「ReactのHooks」や「VueのComposition API」でも、ロジックのローカル化、(巨大なstore管理やグローバルJSファイルの肥大化といった)“持て余した分離”が避けられる傾向にあります。

同様の悩みを、Elixir/Phoenixスタックも上手く受け止めてきたのです。

2. 型安全・再利用性を犠牲にしない柔軟な実装が可能に

もちろんこのアプローチが“なんでもJSをべた書き可能”という乱雑さにつながる恐れもあります。

ただ、Phoenix LiveViewは「特殊なタグ(type指定)」と「命名規則(.MyHookName)」によって、モジュールスコープを意識したうえで競合やバグを防止。

また、JSフックは「マウント時のみイベントをバインド」「他イベントを汚染しない」ため、グローバルに悪影響を与えにくい。

この設計思想が、RailsにおけるStimulusや、最近のTurboフレーム、さらにはNext.jsのServer Componentsにも通じる「サーバサイド+最小限のクライアントJS」という潮流によく合致しています。


実践でここがスゴイ!「アルバムリンクをワンクリックコピー」機能の例

では、実際にどんな風に利用できるのか。

今回の記事では、楽曲アルバムのページに「ワンクリックでURLをコピーするボタンを追加したい」というごくシンプルなUI要件を題材に、その実装が紹介されています。

その中の重要部分を引用します:

“We’re setting up a click event listener. When someone clicks the button, we use the browser’s clipboard API to copy the current page URL. Then we find that hidden ‘Copied’ text, show it for 2 seconds as feedback, then hide it again.”

Phoenix LiveView Colocated Hooks and JavaScript

この通り、UIボタン側には

html
<button phx-hook=".CopyLink" ...>
<!-- アイコンや "Copied" テキスト -->
</button>

を設置し、そのままHEEx内に下記のようなJS(Colocated Hook)を記述します。

“`html

“`

この構成により、

  • どのコンポーネントがどのフック依存か明快
  • クリックイベントやDOM構造の認識ズレが発生しづらい
  • “この箇所にだけ必要なJS”を安全に導入

という、メリットを最大限活かせます。


さらなる拡張性──Colocated JSによるUI制御の新しい流れ

LiveView 1.1では「colocated hooks」だけでなく、「colocated JS」も導入されました。

これは、より一般的なJSスニペットの局所的な注入を可能にするもので、例えば「要約テキストの“全文表示/折りたたみ”」のような動的UIスイッチ構築にも活躍します。

記事にも以下のようなスニペットが紹介されています。

“`html

“`

このスタイルで“イベント検知→DOM操作”が可能に。

他のフレームワークで言う「ローカルなJSファイル」や「Svelteの

タイトルとURLをコピーしました