How Laravel Livewire works
calebporzio.com
calebporzio.com
Why do you prefer to send HTML over the wire?
For one it adds a simple set of primitives I need to learn on top of HTML (a basic tech to know), so no large JS frameworks or patterns to learn.
Secondly, it's really fast with regards to development speed, application speed and just getting up to speed in general. A basic MVC framework (such as Django but others also) is all you need in addition to the primitives I talked about above. With modern frameworks such as Vue or React, I need a backend with basically the Model and Controller part and then a different framework for the View part.
The challenge can come if/when your backend needs to start servicing a mobile app, or some other channel that doesn't use HTML.
But again if you know that won't happen, no need to prematurely optimize for it.
It's a totally different ballgame if the app is mostly client-side utility anyway (calculators, etc), but the HTML + a bit of JS handling Service Worker and offline presentation should enable a great offline experience. I haven't seen it done in a large scale, but it should work.
2. Or you expose an API for those mobile clients. You might still be saving more work (but this is subjective and depends on the project).
> Why should only <a> and <form> be able to make HTTP requests?
> Why should only click & submit events trigger them?
> Why should only GET & POST be available?
> Why should you only be able to replace the entire screen?
I love their motivation points, but do you really need 11kb of gzipped js to do this? At that point it's almost like a frontend library itself (mithriljs is only 9.5kb gzipped).
It could certainly be smaller, but to support things like CSS transitions and so forth it takes some code. I've tried to keep the power-to-weight ratio high by creating a rich events model and extensions mechanism to take pressure off the core library. My goal was to keep it under 10k, but I couldn't do it (I may pull SSE and WebSocket support out to try to tuck it under 10k again.)
On the other hand, compare it with the average image on a website, and 11k isn't bad.
Although I do feel Phoenix Liveview is a better option because they implement sockets.
Also saw this update today they will allow you to trigger javascript on the client without the sever round trip, it's one of the things people get a bit stuck understanding. Generally they think to pop open a modal or menu requires a round trip to the server but really you should be using Alpine.js or similar for such things. This new pending update remove the requirement of needing a framework like Alpine. https://github.com/phoenixframework/phoenix_live_view/pull/1...
I've built frontends in React and feel I have a fairly high level of expertise in VueJS; I actually got the sense that Blazor borrows quite a few ideas from VueJS. A major missing component IMHO is a good reactive state store like MobX..
I dont think we're going to go back to that anytime soon, the performance hit is just too big compared to a well written js implementation.
To be fair, Blazor uses wasm, which is significantly better then the cross-compilation of GWT back then. nonetheless, the performance (esp. time to first render) is just not good enough for a lot of consumer facing apps
It definitely has its niche though. Especially if you're able to cache the .net runtime that gets executed through wasm locally (PWA style)
However I don’t think javascript is the fundamental blocker. When people say they dislike building SPAs, they probably mean they dislike APIs and the whole circus of double validations, error catching, form handling and cache invalidations that come with a React/Vue SPA.
Inertiajs[1] is a really solid middle ground of MVC goodness and client side interactivity.
[1] - https://inertiajs.com
If this style gains traction, are we in for the same range of teething issues for a few years?
On routing, I know Phoenix LiveView for instance does have a way to do navigation over the websocket but I don't know enough about it to know if it makes the same mistakes/introduces the same issues that SPAs did. Looking at this article though I'm guessing the Laravel Livewire one doesn't address routing at all (because what would you hydrate on the server?) and you'd be routing in a normal server-rendered way.
1) Routing is handled
2) open new tab is not handled maybe, i am not sure what the problem is
3) back button work on phoenix liveview, we just use the normal push
4) back button state restoration is easy, it is made for it
5) scroll restoration depends of what you did
6) Sane loading indicators are built in and introduced already
7) accessibility is a non problem, this is just normal HTML, not generated div that create a mess
8) keyboard interaction are better than default SPA but probably could be better ? Idk
9) Feeling snappy/reliable... well idk, i feel it is far better than SPA already, but we will see long term
If you middle click (or right click > Open in new tab) a link on HN then it'll open that link in a new tab. Loads of SPAs break this and it's really annoying if you're used to using it. I'm not sure if Phoenix live navigation helpers break it or not, do you know?
Examples like multi-level routing with tabs/subtabs. If I "open in background tab" the "Performance" tab inside the "Mobile" tab, will it work (e.g. send me to myapp.com/admin/mobile/performance)?
Just out of ignorant curiosity, if I "open in background tab" from a LiveView app, will I get the same server state session or a fresh one?
Where I see it taking off are places which don't yet have a CTO you need to convince: early stage startups or small companies who need to move more quickly, reduce maintenance and bug overheads and don't have the cash for a multi-disciplined team.
Unicorn is well on its way to being really good. It is easy to use and integrates with Django well.
These tools are contributing to the lowering of code quality standards, regardless of their intentions or the rigidity of their coding standards. They're good tools once you understand how they work, but most of its users use it precisely so they don't have to.
For lots of working developers out there, "ship stuff" is their job, and you can't expect every single dev to understand the stack they work in end-to-end and to build their own plumbing each time, just for the sake of some ideal of knowledge.
It's a straw man to say that frameworks "lower code quality standards". I would argue in a lot of cases it's the opposite and they help codify best practices for the 80% of web applications that are the same, instead of everyone having their own custom implementations of templating, event handling, auth, caching, etc...
Would you rather have journeyman programmers building crappy templates and inefficient controller logic, or crappy auth systems and slow storage layers?
Frameworks provide guard rails and let less skilled developers be more productive as they get better over time. One can hope that some will dig in under the hood to learn more, but if they don't, so be it. At least they're not building your auth system or rolling their own hashing libraries.
I find Livewire a pleasure to work with. It's certainly not a hammer for every nail, but a refreshing step away from the JavaScript madness without sacrificing all of the good parts about it (anything async, basically).
Breeze and Jetstream are more recent optional packages, and Laravel is still productive without them. So effectively you are saying, “I wish Docker Hub had fewer images available, it’s more productive without.” Pfffft
The "hop in and be productive" part is directly related to Laravel being pretty opinionated. It's hard to have the one without the other. I think it's comparable to Steve Jobs, who had pretty strong opinions about certain things, too. The end result is a "product" that doesn't try to be the right fit for everyone.
Livewire, just like Jetstream[1] etc. is opt-in. When Jetstream was introduced, there was quite an uproar (by parts of the community) about Laravel forcing users into Livewire or Inertia[2]. The end result was (imho) a very healthy shift in communication around it (to emphasize the opt-in part), followed by the introduction of Breeze[3], which goes to show that Taylor does recognize the reservations some people may have about those new shiny toys.
It's a very natural thing that big projects like that will have an ever-growing feature set. That is an important part of keeping existing users excited. The Jetstream-discussion has been an important lesson for the team (I hope) and I'm glad it ended the way it did.
You can still build your Laravel app in a pretty similar fashion as you would have done 5 years ago and if you want, you can make use of the recent additions, so I think there's not too much to worry about to be honest. If you have outgrown the magic, isn't it pretty amazing that you can drop down one level of abstraction and just use symfony? Also, do you think you would've grasped many of the underlying features of symfony, if it wasn't for Laravel's opinionated wrapping in a nicer syntax (pardon my oversimplification)?
Nevertheless, I think it's good to keep up the warning signs and have this discussion from time to time. ;-)
[1] https://github.com/laravel/jetstream [2] https://inertiajs.com/ [3] https://github.com/laravel/breeze
What I found is that this is a good idea in _some_ contexts, namely if you can and want to treat the browser as a rendering engine for state snapshots. If you break with that assumption, you want something else, or you'll be slowly creeping into an ad-hoc, complicated mess, where there is no clear abstraction boundary for the UI. You just end up smearing it all over your code.
There are some fundamental reasons for this.
A technical one is that HTML isn't just data representation. It also dominates the shape of your UI tree. Do we really want to complect these things? The separation between HTML, CSS and JS is extremely leaky and blurry. The more you try to pull them apart, the more painful it gets. It's also the ultimate de-normalization of your data. Meaning it's going to be a huge PITA to coordinate if its not done in one coherent place.
Another issue is that you are breaking a separation of concerns and encapsulation. Does the server really have to know how I just toggled a menu, rearranged some widgets with drag-n-drop or switched a stylesheet? Trivially no. The server might care about some of that happening after the fact, but almost never about the details of how.
But this gets even more pronounced when you implement features touching on security, consistency and reliability. With a clearer UI and server separation you have two distinct mental models or modes. On the front-end you only care about the user experience and optimize for that: Immediate feedback, guiding messages, visualization and transitions. You can treat the user as your best friend and fulfill all of their wishes. But on the server you treat them as an incompetent stranger and/or as and adversary. Because, you know, its the Web! With this separation you enable focus and avoid mental taxation mixing things up. It's ultimately a simplification in the pure sense of the word.
With all that said, I don't doubt that many find this paradigm useful, especially because of what you said in your last sentence. And I'm sure that in many cases you can work around the problems I mentioned, or even model them well if you don't break with the assumption I mentioned at the start. But if you do anything interesting _in_ the browser you'll likely be forced to patch over the fact that you are now smearing your front-end logic all over places.
It looks like the PHP version uses AJAX requests instead, but most importantly it doesn't persist any state on the server continuously. And then it looks like client requests send the current state, as well as checksums etc. to keep it secure. Then the server spins up a new instance of the class, hydrates it with the current state, runs the requested operation and returns the dom patch.
It looks like LiveView has much smaller requests/responses and both client and server do much less work. But the tradeoff of that is that you have lots of Elixir processes, which I guess pretty much only works with something like the BEAM. And you have to be careful about memory because those processes all hold a client's state. If you want to display a page of database results then that's fine but you'll want to clear them from the state instead of keeping them in memory for as long as the user is on the page. And of course then you're going to lose some performance if you need that data again for a future operation by the client. The Livewire approach doesn't force you to think about that, you don't have the choice to hold the state in memory.
Website: https://laravel-livewire.com