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.