anon9372508

anon9372508

Looking for input about how to better approch JS development in Phoenix (not just liveview)

First Hello.

Secondly:
I want declare my intent before I say anything else so that I’m not misunderstood.
I want to have a conversation that can typically become very contentious.
I don’t wish to be contentious, disrespectful or contrary for the sake of it.
That is not my intent.
I love the free work that other people have created for me that I have not ever had to pay for.
I’m not saying any of the following to be disrespectful of their hard work. So with that thanks for everything.

What is my intent?

My intent is to address my core concerns and to get input about how I can already use existing solutions or possibly develop a new solution to address these core concerns.

I think by addressing these concerns we can make phoenix better for everyone and possibly attract other typically front end heavy developers to adopt phoenix.

What I wish I had in Phoenix.

Following after this are my core concerns and wants as I think they best describe the flow.
In general I want to use phoenix as my primary framework and find a better way to make more expressive js applications in it. I love liveview and fully understand it, there are just these tradeoffs I keep finding myself wishing I didn’t have to make and I wonder if there is a better middle ground where we don’t have to make these compromises. I realize that some of my asks may never happen, I still think they are worth sharing so that 1: You considered the idea, 2: we have meaningful conversation that maybe brings to life new ideas.

So with that lets begin.

The HTTP REQUEST:

1A:
I want to use Phoenix as a primary router for my initial request and provide SSR for SEO.
I think the phoenix router / plug already does a good enough job of this and see this as the right way to address that concern.
Also I think Phoenix controllers do good enough for this for the great majority of projects.

1B:
I want all sequential requests to not require a full page load. (IE hydrate then hand off)
I am aware that live sessions and patch requests via liveview can address this.
I am aware that liveview does a dom diff via the socket so no need to call that out.
I do want to come back to this later as I feel liveview is coupled to the socket which I kind of see as the primary barrier to working with other frameworks like svelte or astro.

I feel the compromise of prefetching like other frameworks do would not compromise on performance significantly and possibly would make it much more easier to integrate these other framework with phoenix for SSR. I would love to see something like sveltekit:prefetch or @astrojs/prefetch for all sequential requests personally

1C:
I am aware that liveview mount callback can also addresses the initial request for SSR/SEO 1A

The Template And Code Organization

2A:
I want to use HEEX templates for general HTML and componentizing blocks of markup.
I know functional components already do a good enough job for this.

2B:
I would like to have scoped JS like that of other front end frameworks built in to the heex template
Likewise I would like to have scoped CSS like that of many of the frontend frameworks built in to the heex template.

2C:
I know JS hooks solves alot of these issues, but they really don’t feel well organized in my projects and leave me feeling like they are a compromise and not a solution. I tend to wish they had better proximity to the code elements they relate to rather than just living in my assets/js folder.
Also having to use hooks as the primary way of code splitting for your JS is not great, though it does work.
I believe I seen something possibly in the works for better organizing hooks so I guess there is some solutions for that. Though at the end of the day they are still just hooks. It would be nice to have a way outside of live view specifically and something more integrated as a part of heex in general when dealing with JS. Given heex is about embedding elixir in html and the fact html is so closely tied into CSS and JS it seems integrating support specifically in heex more sense IMO.

2D:
Same goes for Phoenix.LiveView.JS.
Its just not as pleasant of an experience developing UI interactions with LV.JS as it is working in say Svelte, Vue, ect components. I tend to feel less confident about working in this area of my codebase when working with LV. This is one of the major reasons I wish for scoped js in the heex templates as to keep the related code closer to the areas they relate to. I don’t know how I feel about just throwing in a script tag into these templates either.

The Event Lifecycle and the Socket.

3A:
It would look as if the great majority of compromises made are the result of the web socket.
I would ask:

  • Is the performance gained really worth it?
  • Can we have relative performance but open up more possibilities by doing it differently?

3B:
We still have Channels for when we really need that pubsub via sockets.

3C:
Server Sent Events are also a possibility.

3D:
https://hologram.page/ I think shows some of these trade offs in terms of the websocket and requiring network for things that maybe should stay client side till they need pushed to the server. Consider Offline mode and how the socket has been a barrier for that.

3E:
Page transitions and other more rich interactivity via js feels impossible with liveview. Again I feel this is the tradeoff as a result of the socket.

3F:
Change tracking in LV and Client side only state is a real battle. It tends to make me think maybe this does not need to be statefull on server after all. But then I realize the pain of duplicating models on the client to replicate that of the models on the server. There has to be a better way even if the sever is the source of truth. Let alone the compromise of offline mode or service workers, push events ect.

My conclusions so far:

  • I love phoenix, and want to keep using it as my main application.
  • I like the general idea of liveview but feel at odds with it when I compared to other js solutions.
  • I wish I had a more unified development experience (mono repo) when working with other JS frameworks inside of Phoenix. I realize this was how we got to liveview.
  • The socket requires a lot of tradeoffs even when using channels.
  • I’m not sure the trade offs are worth it for the socket given there are other like solutions.

How did I get to this place?

I’ve spent some time trying to figure out how to get the best of both worlds.

  • Phoenix + Vue,
  • Phoenix + Svelte (including live svelte)
  • Phoenix + liveview + other js frameworks

I recently deiced to give mix phx.new --no-assets --no-live a try and see what its like to just divorce from liveview as much as I could and write vanilla ES modules + channels and once trying server sent events.

it was not a horrible experience but it did highlight what I got out of the box for free.
In someways it inspired me to want more freedoms at the cost of out of the box features.
For example I’m not sure I will be going back to daisy UI or even tailwind moving forward.

Any ways I don’t mean this to be a rant about liveview,
I find myself constantly thinking about these problems and find myself even telling myself that I should just develop a whole new solution.

I would love to see what other people say about what I have said here.

Thanks for reading this.

Most Liked

Jskalc

Jskalc

Hello :waving_hand: I wanted to add my 2 cents here, as I had similar “problems” with LiveView and currently I’m quite satisfied with my workflow. For context, I’m the creator of LiveVue library, and I have quite a deep familiarity and preference for Vue frontend framework. I gave a talk “Why mixing LiveView and a frontend framework is a great idea” during ElixirConfEU 2025, recording is not yet out but you can check slides here (desktop-optimized)

So, in short:

  • I love declarative approach of LiveView, and having a stateful connection to the server which allows to skip writing API endpoints
  • I don’t like JS interop - JS module is limiting and imperative, hooks are detached and imperative as well.
  • LiveComponents are nice but have awkward API for updates, and can’t handle handle_info etc. Also doesn’t solve client side state.

What I want:

  • Be able to decide where to keep state - on server, or on client?
  • Have declarative rendering on both sides
  • Use amazing features of LiveView without problems

My current approach:

  • Use LiveVue in the same way as Interia.js does - one top-level Vue component per LiveView
  • Ditch HEEX, render whole HTML in Vue.
  • LiveView is responsible for updating props which are transparently propagated to the frontend.
  • Vue can decide if given user action should be handled locally or propagated to the server
  • I’m colocating Elixir files and Vue files.
  • live-navigate is fast, since it only updates props of a Vue component. Update is synchronous, no flash of unstyled content.
  • SSR is available and quite fast.
  • Using Vite instead of ESbuild (amazing DX)

Using that approach is not yet as straightforward as I’d like, I’m improving library to make it so (eg colocating requires moving node_modules to root etc). Igniter installer is also coming. Not sure if it checks all your boxes, but wanted to highlight there’s a possibility to do something like this without using Inertia :wink:

Some screenshots from my current project.



10
Post #8
bartblast

bartblast

Creator of Hologram

Hologram is fundamentally different from LiveView. While LiveView sends diffs over the wire, Hologram transpiles your Elixir code to JavaScript for client-side state and instant DOM updates.

You’re technically right that JS is abstracted away, but the development experience differs - there’s no abstraction leakage to deal with due to transpilation.

Worth giving it those 15 minutes - there’s a big update coming within the next 2 weeks with several roadmap items completed! :grinning_face_with_smiling_eyes:

sodapopcan

sodapopcan

Poking my nose in here for this massive thread I’ve been silently following to confirm yes: I value this a LOT. I really dislike the “what if we need an API” argument because:

  1. What if we don’t?
  2. If we do, I don’t see having a separate customer-only web API as a bad thing. Provided you have “skinny-controller” design this isn’t a herculean feat and lets you draw a firm line between what is internal v external. Also, these days we have Ash which makes this trivial :slight_smile:

Where Next?

Popular in Discussions Top

ben-pr-p
In general I’ve been sticking to this community style guide GitHub - christopheradams/elixir_style_guide: A community driven style guide ...
New
Rustixir
Hi everyone, im working on find best language/framework/system for high concurrency, high performance and stable performance after wor...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
Ankhers
Just a little information upfront. Generally speaking, if I feel like I need to either break a pipe chain or use an anonymous function in...
New
IVR
Hi all, I’ve seen a number of related threads in the past, but I’d still be very curious to hear an up-to-date opinion on this topic. I...
New
rower687
Hi all, I’ve been reading a lot about the “let it crash” term and how supervising processes and the whole messaging passing make an elixi...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
Owens
Hello all, I am developing a new mobile app with Flutter frontend and Phoenix backend. The mobile app has real-time task management and c...
New
MarioFlach
Hello, I want to share a project I’ve been working on for a while: https://github.com/almightycouch/gitgud Background Some time ago I ...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

Other popular topics Top

Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54250 245
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

We're in Beta

About us Mission Statement