Been using Liveview in production since 0.1.0. The cognitive overhead is much lower and I can’t say enough good things about it. Simply put, it made a herculean task of building desktop-like software, merely difficult. That is truly innovation. Fire And Motion – Joel on Software covers my thoughts pretty well on this. While everyone else is busy keeping up with the tech and wasting their time, liveview just works.
Here are some notes:
- I designed the frontend so that the user rarely has to hit the server unless they actually new data, so I am not running into any of the downsides of the approach at the cost of sending 10k-20k extra uncompressed data upfront. The compressed page is still 30k though.
- Each livesocket uses some amount of memory on connection and holds it in the state. Early on, I had to manually hibernate the threads. This was added by default in 0.5.0. This is super-important to be able to scale the number of concurrent users. I made sure that most of the user actions do not go back to the server by using hooks and css, so this memory saving is real. More on that later.
- Security - it took a while to figure out the difference between the different mount options in liveview. For instance, to have the user_id available with both liveview and non-liveview, I had to use conn.assign and Plug.Conn.put_session and read the session from the liveview.
- Speaking of sessions, I have been using cookies to store the session and include user preferences. I was shortening the cookie fields from “pref” → “p” in the cookie to save space, but what I didn’t realize is that everything would end up in the session cookie. I’m not sure how I missed it, but I was awfully close to running out of cookie space. Eventually, I had to make a guid in the cookie, store everything in ETS, sync the ETS prefs to DB, and make a distributed cache update on ETS for multiple machines if a pref was changed. Quite frankly, the distributed cache update was the easy part.
- Optimistic UI - if every menu update had to go back to the server, that would be really irritating. I’ve been using CSS instead of alpine with No Javascript Clientside Phoenix Live View Modals
- Alpine - on that note, I’m not sure what the point of using Alpine is. It just seems to add another layer to have to debug. I tried it and then re-wrote what I needed in maybe 50 lines of hooks.
- Form recovery is important to get right. If a user changes to a different tab, what will happen is eventually the browser will remove it from memory on mobile. Form recovery gets called quite a bit for me.
- I’ve been strictly using stateful components. The rendering time is in a single process and I haven’t tried improving it. My main page has about 15 components which take 40ms to render. I’m not sure if changing these to liveview would make life more or less complex. I’m still on 0.15.4. Unfortunately, I’m not looking forward to 0.16.0 since I have to change all my stateful components to heex.
- Testing - I haven’t written a single liveview test. There have been occasional small breakages on upgrade, but those would not have been picked up anyway by tests.
- Rendering size - websocket is passing about 40k-70k of data on an update. Adding compress: true to the socket options saved me about 50ms on update for far away users.
- Hooks - Overall, I have 350 lines of js. The user doesn’t need to contact the server unless they are actually executing an update or need a re-render. ’
- Typeahead - there are so many tutorials that use datalist including the default from the liveview examples. DO NOT DO THIS UNLESS YOU HAVE EXACT MATCHES. Each browser implements datalist slightly differently, but more importantly, it will further filter your results based on a String.contains. So if your result doesn’t have a comma, but the input does, the result won’t show. Instead, use relative_div → absolute_div → ul / span / etc and use phx-click and careful with safari.
- Safari is annoying in general. Not to do with LiveView, but sometimes items where not clickable with phx-click. This is a Safari’ism, where you can’t put phx-click on a div, etc.
- Breaking changes - it’s 0.x software which is remarkably stable. But there will be breaking changes on upgrades. I suspect the churn is still less than the js ecosystem though.
- Sending events on the backend is great for GUI design/updates.
- Regarding fly.io, I’m planning to use it once I migrate a lot of my read only data to sqlite. At that point, the update latency will be ridiculously low.
Yah, what can I say really. Liveview is fantastic.