Hi! Today, after a couple weeks of development I’ve released v0.1 of LiveVue.
It’s a seamless integration of Vue and Phoenix LiveView, introducing E2E reactivity of server and client-side state.
Started as a fork of LiveSvelte, evolved to use Vite and a slightly different syntax.
Why you might want to use it?
Your client-side state grows and it’s hard to deal with it
You misses declarative rendering on the client side
You’d like to use a vast ecosystem of Vue libraries
You’d like to introduce animations
You like Vue
Why I created it, if LiveSvelte already exists?
I love Vue and was missing it’s DX and ecosystem (VueUse is amazing)
More options are always better (right? )
Vite gives you best-in-class stateful-hot-reload, and paired with stateful-hot reload on the server you have a stateful hot reload across the whole stack (which is HUGE!)
Features:
E2E reactivity
Support for phx-* attributes inside Vue components
Uses Vite for an amazing DX
Server Side Rendering (optional)
Vue/Phoenix slots interop
Vue event handlers can be defined with JS module
~V sigil for inline Vue component definition
Plans for the future:
On-demand lazy-loading of components
Optimised payload with LiveJson or similar
Better tests
Dedicated page with examples
Guide of handling changesets & forms
Pinia support?
An example
defmodule LiveVueExamplesWeb.LiveCounter do
use LiveVueExamplesWeb, :live_view
def render(assigns) do
~H"""
<.vue
count={@count}
v-component="Counter"
v-socket={@socket}
v-on:inc={JS.push("inc")}
/>
"""
end
def mount(_params, _session, socket) do
{:ok, assign(socket, :counter, 0)}
end
def handle_event("inc", %{"value" => diff}, socket) do
{:noreply, update(socket, :count, &(&1 + diff))}
end
end
@ added to Vite & typescript paths. Points to assets, so it’s possible to import files from @/img/someimage.svg. To migrate, see assets/copy/tsconfig.json and assets/copy/vite.config.js
Added Vite types to tsconfig.json to support special imports, eg. svg. To migrate, add "types": ["vite/client"].
Added possibility to colocate Vue files in lib directory. To migrate, copy assets/copy/vue/index.js to your project.
Version 0.3.1 has been released. Lazy loading components is now supported Your app.js doesn’t have to grow as your application grow! SSR renders these lazy components + preload hints, so it has a minimal impact on performance
How to do it? Simply import files lazily using Vite
in this example, Vue files colocated with elixir files will be loaded on-demand, while files in assets/vue will be always part of the app.js bundle. You can decide which files should be loaded on demand.
Another approach:
import component1 from './Component1.vue'
import component2 from './Component2.vue'
export default {
Component1: component1,
Component2: component2,
Component3Lazy: () => import('./Component3.vue')
}
Changelog entries:
0.3.1 - 2024-05-17
Changed
Simplified assets/vue/index.js file - mapping filenames to keys is done by the library. Previous version should still work.
0.3.0 - 2024-05-17
CHANGED
removed esbuild from live_vue, package.json points directly to assets/js/live_vue
added support to lazy loading components. See more in README. To migrate, ensure all steps from installation are up-to-date.
The name was a natural consequence of following LiveSvelte.
In written english it’s perfect. Short, easy to comprehend and understand.
In spoken english - yes, it’s not perfect. I realised it too late, after publishing the initial release and generating a bit of a buzz around it.
My idea to solve it - in speech it can be referred to as LiveVuejs. I added a section to the official FAQ. I’d prefer to avoid renaming package and all references to it.
I totally get the part where it matches the LiveSvelte thing, it definitely follows logically. It’s just that it will, I 100% guarantee you, will lead to avoidable confusion.
When you have the choice of naming it literally anything else, why not make that choice, instead of stepping on the toes of what is possibly the Elixir community’s flagship project?
VueLive has almost the same problem, doesn’t it? I can imagine when speaking someone might reply “you meant LiveView?” and then you’d need to explain “yeah but I mean frontend framework Vue”
And also, it’s a Vue extension to Phoenix, not the other way around. Hard to market it that way.
VueLive is a step in the right direction, but I agree that it’s also confusing.
There’s no rush on picking a name. I find that if you give these things a bit of time, something will pop into your head when you’re doing the dishes or something like that.
Maybe something like LiveInterVue? As in “LiveView with Vue Interop”.
VueJsLive is also an option. A little awkward but gets the point across pretty well IMO. It’s Vue.js, but Live.
I’ll see if I can think of anything else. I don’t want to be the guy who only brings up problems and offers no solutions. But this one is tough because the names are like, the same.
I seem to be in a minority that thinks that this name is fine. We have LiveSvelte, I’m sure we will soon have LiveReact, LiveSolid, LiveQwik and whatnot. It will hurt the discoverability of this one project and the phonetic similarity is less of a problem when the distinction in written text is clear.
Another thing to consider is the fact that this project started as a fork of LiveSvelte. I’m unsure how much it’s deviated since the fork, but if there is still a sizable chunk of the original code remaining you could team up with @woutdp and extract the core as a new library, LiveSPA, which is just an integration tool for JS frontends. Then in the docs you can have an Integrating with Svelte, Integrating with Vue, Integrating with … and drop the LiveFramework names altogether. I’m unsure if it’s possible but having one place in the docs to go to learn how to add any framework would be great as the docs are very scattered as is.
Elixir is pretty dynamic. You could have the real core in LiveSPA. The Vue specific changes you’ve made in LiveSPA.Vue and the Svelte specific config in LiveSPA.Svelte
I’d like to have a single interface for these kinds of libraries, but we’d have to make sure it’s the correct abstraction. LiveVue does some things different from LiveSvelte, for example it uses Vite instead of Esbuild. So the setup wouldn’t be the same.
I’m more in favor of manually converging the libraries. LiveSvelte can learn from LiveVue. For example, maybe it would be an idea of having both an Esbuild (which I picked since it’s closer to the documentation Elixir and the default setup you get with a Phoenix project) and a Vite setup which is a bit more modern as a build tool in the frontend world.
What I’m trying to say is that even though the libraries are a solution to the same problem, their implementation (and future other potential frameworks) might have completely different ways of solving things. Currently I don’t see how a shared library might make things easier for users and for maintainers. But a manual convergence of the libraries does make sense, and if enough frameworks get implemented and we see certain patterns that are always the same, then it might make sense to do it at that point.