👨‍💻

私たちはHEExが大好きです -- YouTube チャンネル daimon.ex 第2回解説

2024/03/21に公開

動画

https://youtu.be/TiBz6cCByRQ

HEExとは何か

HEEx(エイチイーイーエックス、ヒークス)は2021年夏に登場した比較的新しいHTMLテンプレートエンジンです。ElixirにはEExという名前の汎用的な(HTMLに特化しない)テンプレートエンジンが従来からあります。HEExをEExの拡張版です。

HTMLタグの属性にアサインを埋め込む場合の新しい書き方

HEExの第1の特徴は、HTMLタグの内側、属性の値にアサインを埋め込む場合に波カッコが使えるようになったことです。

次に示すのは、EExのコーディング例です:

<div class="<%= @k %>">
  <%= @score %>
</div>

これがHEExではこうなります:

<div class={@k}>
  <%= @score %>
</div>

従来の書き方には角カッコが入れ子になるため読みづらいという欠点がありました。また、新しい書き方の方が短く簡潔です。

関数コンポーネント

HEExの第2の特徴は、関数コンポーネントというものが加わったことです。

EExでは、テンプレート square.html.eex を別のテンプレートに埋め込む時、次のように記述していました:

<%= render "square.html", letter: "A", bg_color: "bg-red-600" %>

HEExでは、テンプレート square.html.heex を別のテンプレートに埋め込む場合、次のように書くことになります:

<.square letter="A" bg_color="bg-red-600" />

Phoenix 1.7 で render 関数を用いるとエラーが発生します。この関数を引き続き使い続けたい場合は、mix.exs の関数 depsphoenix_view というライブラリを組み込む必要があります。

{:phoenix_view, "~> 2.0"}

~H シギル

動画では触れませんでしたが、テンプレート square.html.heex のコードを ~H シギルを用いて関数の中に埋め込むことができます。

例えば、lib/daimon002_web/controllers/page_html ディレクトリに square.html.heex という名前のファイルがあり、それが次のような内容を持っていたとします:

<div class={"w-24 h-24 #{@bg_color} text-white flex justify-center items-center"}>
  <%= @letter %>
</div>

また、同じディレクトリに page_html.ex というファイルがあり、次のように Daimon002Web.PageHTML モジュールが定義されていたとします:

defmodule Daimon002Web.PageHTML do
  use Daimon002Web, :html

  embed_templates "page_html/*"
end

この時、square.html.heex を削除して、次のように書き換えることができます。

defmodule Daimon002Web.PageHTML do
  use Daimon002Web, :html

  embed_templates "page_html/*"

  defp square(assigns) do
    ~H"""
    <div
      class={"w-24 h-24 #{@bg_color} text-white flex justify-center items-center"}>
      <%= @letter %>
    </div>
    """
  end
end

関数コンポーネントを Daimon002Web.PageHTML モジュールの関数 square/1 として表現することと、square.html.heex というHEExテンプレートして表現することは同値です。そのため、上記のような書き換えをした時に、square.html.heex を削除しないと例外 CompileError が発生し、次のようなエラーメッセージがログに出力されます。

== Compilation error in file lib/daimon002_web/controllers/page_html.ex ==
** (CompileError) lib/daimon002_web/controllers/page_html.ex: cannot compile file (errors have been logged)
    lib/daimon002_web/controllers/page_html.ex:6: (module)
    (elixir 1.16.1) lib/kernel/parallel_compiler.ex:428: anonymous fn/5 in Kernel.ParallelCompiler.spawn_workers/8
Compiling 1 file (.ex)
    error: defp square/1 already defined as def in lib/daimon002_web/controllers/page_html.ex:4
    │
  6 │   defp square(assigns) do
    │        ^
    │
    └─ lib/daimon002_web/controllers/page_html.ex:6:8

参考資料

Discussion