Decouple HEEx from LiveView?

While working on a Phoenix-related project, I stumbled upon an interesting issue - it is impossible to use HEEx templates without having LiveView as a dependency. The culprit is that the HTML Engine for it is inside of Phoenix LiveVIew: phoenix_live_view/html_engine.ex at v0.17.11 · phoenixframework/phoenix_live_view · GitHub

This was really annoying to me, since I would expect that HEEx is nothing more than a templating language that should work regardless if the app is using LiveView or not. For very simple apps, I don’t think it’s worth the extra work for having LiveView. So now I need to have LiveView as a dependency, even though I have 0 live views! There was a suggestion on the Elixir Slack that we could move it out of the LiveView package, but I also want to hear everyone’s thoughts here.


I’m using heex as a templating engine which is very nice, but

This was my expectation at first as well, see this comment in the original HEEx roadmap issue: HEEx roadmap · Issue #1506 · phoenixframework/phoenix_live_view · GitHub. I’m not sure if they are waiting for a v1 to push the dependency out of LiveView or have abandoned the plans entirely. I also think it’s kind of overkill tbh, I’d rather have it as part of phoenix_html for instance.

1 Like

I’d also like to see this happen. I like using Heex, but not LiveView. It would be nice to use it without also pulling in a LiveView-related code that I don’t use.

There are no plans to extract it at the moment but I also want to point out that “without pulling LiveView related code that I don’t use” is most likely a micro-optimization. I just checked LiveView source code and at the moment it defines 57 modules. Plus a quick estimate shows that roughly half of these modules (~28) have Engine/HEEx functionality. That is tiny compared to the number of modules you will have in your application. For example, Livebook has 959 modules, and that’s not counting the ones coming from Elixir or Erlang/OTP. Therefore, it is hard to see how “not pulling LiveView-related code” is going to give any meaningful benefit.

One could argue that, if you don’t care about LiveView, having to debug only the HEEx bits is going to be easier, and I would agree with that. But that comes at the cost of putting a layer (and a dependency) between LiveView and HEEx, which will make the lives of everyone using, maintaining, and debugging LiveView - which is perhaps the majority - much harder. So the costs are really hard to justify here.

And it is not like we are averse with breaking things apart. We extracted Phoenix.HTML, Phoenix.PubSub, and Phoenix.View/Template (the latter pretty much based on user demand) in the past. And it actually has led to the downside of fragmenting the documentation - which is a complaint that needs to be addressed… So breaking LV+HEEx might happen in the future but 99% not worth it now.


I agree that having phoenix_live_view as a necessary dependency in a Phoenix application is a pragmatic choice. I’ve had to worked with over-factored applications before in other languages and I agree it is laborious to coordinate changes across packages that can take the joy out of programming.

For my specific case, I want to use Heex without using Phoenix at all, which I should have mentioned in my reply. I have the beginnings of a single-script-file static site generator that I coded up today that uses heex for templating. Because phoenix_live_view also depends on phoenix, my “static site generator” ends up also bringing in Phoenix and its dependencies as well. :laughing:

iex(1)> Mix.install([:phoenix_live_view], force: true)
Resolving Hex dependencies...
Resolution completed in 0.332s
  castore 1.0.1
  mime 2.0.3
  phoenix 1.7.2
  phoenix_html 3.3.1
  phoenix_live_view 0.18.18
  phoenix_pubsub 2.1.1
  phoenix_template 1.0.1
  plug 1.14.2
  plug_crypto 1.2.5
  telemetry 1.2.1
  websock 0.5.1
  websock_adapter 0.5.1

It would be nice if it is broken out one day, but also understand if it isn’t, or if it takes a while. Certainly won’t stop me from using it till then :smile: . It really is a great templating language.


I’m using heex as a template engine to create PDFs. Was using py/jinja2 before and I have to say (as objectively as i can express myself) heex is easily 1000 times better. But its really good hidden in LV. If you want to use it - and can’t use embed_templates - you have to

  require EEx

  source = "sample.html.heex"

    # Phoenix.LiveView.HTMLEngine pre 0.18
    engine: Phoenix.LiveView.Engine,
    caller: __ENV__,
    source: source

  def render(assigns) do
    sample(assigns) |> Phoenix.HTML.Safe.to_iodata() |> to_string()

which is not obvious and not documented at all.

You’d really make the world a better place if you’d free heex and treat it as a general purpose template engine.
Maybe when LV hits 1.0?


off-topic but can you post a sample of how you do the PDF creation?

1 Like

the ingredients are CSS3 paged media module, tailwind, heex, markdown and prince.xml (paid) as a processor. Be warned that its a little tricky to get tailwind and prince together right now. I will make a post about it.

1 Like

That one is in the phoenix_template package, which you could pull in as well. It includes all the template management you know of phoenix.

I (think) I can’t use embed_templates because I need more control, not because I can’t use it outside Phoenix (which I think is what you mean).