I recently started using htmx (https://htmx.org/) in combination with Django and have become a firm believer of sending HTML 'over the wire' instead of JSON structures that then get used client side.
I personally prefer sending JSON or CSV over the wire, and keeping all presentation logic on the client side. This allows me to adjust the presentation layer based on what's best for each specific client.
I feel that it empowers me as a Backend developer and makes me productive on both the BE and the FE.
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.
If you structure your backend correctly, it should be trivial to build a JSON API on top of your service layer. Unless you're coupling your http endpoints to your service logic.
I'm a Front End Dev and work with SPAs for the past 2 years. Working an offline-enabled PWA powered by Svelte and Redux. Honestly, I have a hunch that an HTML-based oriented development can still provide a great (measured) offline experience, without needing to rebuild wholesale to SPA.
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.
It's not exactly a lot of work to handle HTML for web apps and have an API for mobile clients or services. For example, if you are using Django, just add DRF with some serializers etc and re-use any common backend logic with both frontends.
Performance is the main one. Particularly on older android devices where script execution is absurdly slow, and network traffic is also often slow, pure HTML is a big win.
HTMX (and HTML over the wire) is giving me some hope for frontend development. React / SPAs have their place and are great technologies, but 98% of the time they are not needed.
I'm curious if you can link me to more information on Taconite? I have been explore the techniques used by "HTML over the wire" and htmx and would like to delve deeper into older systems or technologies that were using these before.
yep and thanks to /u/recursivedoubts for delivering an excellent package. I use htmx then mithril for those pages that really need client side interactivity. and it's refreshing.
> 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).
You can tear out some of the stuff (sse support, web sockets) and shrink it ~2k. Do away with the events mechanism and extension points, knock down the configuration options, drop IE support and probably get it down to around 6 or 7k.
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.
I feel that the simplicity of just building on the server and pushing the updates across the wire is where we are heading. So a lot less double up, with regards needing to write both for the server and client. Validation especially will just need to be written once.
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 write a lot of apps in Blazor. And I also think this is where we are heading. Just write code in C# and it works.
Unfortunately Blazor feels a step back compared to something like VueJs but I really like that I don't have to write JavaScript anymore.
The idea isnt new though, GWT has been around since 2006 (the ancient Java version of writing the frontend code in Java, which is then served as JS to the client)
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)
I really like the Blazor tech, but with all the activity around Blazor WASM I'm not sure this is really where things are heading. It's neat that both options work with the same underlying tech(even if converting an app between the two wouldn't be so simple).
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..
Awesome. I’m noticing a ton of “alternative” front end development tools these days: Hotwire, Stimulus Reflex, LiveView, Livewire, etc.
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.
Will we see a bit less SPAs and more of this?
Rails has come up with Hotwire. ASP has something similar I think...only questions is what CTOs will make of this. And front end devs who are super used to doing SPAs won't like this change I fear.
It took SPAs something like 5 years of popularity to get to a place where they are basically fine. I‘m thinking of things like routing, open new tab, back button working, back button state/scroll restoration, sane loading indicators, accessibility, keyboard interaction and feeling generally snappy+reliable. If a movie theater creates their website using next.js today, I probably won‘t notice or mind. A few years ago, when that kind of website went SPA, it made me shudder.
If this style gains traction, are we in for the same range of teething issues for a few years?
That's good to hear. I did not mean to say these are actual problems, since I have never used these tools, only that a new approach needs some care. As long as you don't take over routing most problems fall away. Once you do, it becomes harder.
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?
It would be fresh, but the url will probably give some information to the app about your state, depending of how it is implemented, so it will probably bring up the state that was already stored for that URL.
> 2) open new tab is not handled maybe, i am not sure what the problem is
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?
They would probably not break it, i would have to check, but it is just a `a` link under the hood. You may lose some of the state, depending of how much the url and backend store.
This is definitely a good point. FWIW I think some of these became issues because SPAs were re-inventing a lot more than what these systems are. These are still server-rendered pages so they should feel more like that than they do an SPA, generally.
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.
Probably too much sunk cost at this point, especially with bigger companies who are deeply invested in SPA and developers who have only ever worked with React or other SPA frameworks.
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.
I'm really into the idea of HTML over-the-wire, with Blade templates and PHPUnit tests. No need to split the logic between the backend and the frontend.
However I still need SPA navigation and although there's a Turbo adapter [0], it looks like more of a prototype at the moment.
Laravel abstracted the PHP language enough that there are "Laravel developers" who cannot work without a framework. Now, these gems are going to do the same thing with HTML and Javascript!
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.
Productivity always has side effects, and usually that comes in the form of abstracting away the plumbing to "ship stuff".
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.
If you need to understand deeply how all your tools work to use them, they are not good tools. They serve to abstract knowledge into them. Can you imagine if you needed to understand exactly how a computer does math in order to use Excel?
As a Laravel user, I still avoid Livewire like the plague. Way too much 'magic' and it's not solving any of my real problems. I don't want to waste time learning Livewire because I really don't need to. Same goes for Laravel Breeze, Jetstream, Inertia, i'm sure they're great but I don't need any of it and they are becoming a thing that gets in the way more and more..
As a Laravel user, I am extremely happy about the different paths you can take and I think it's absolutely fantastic that you are _able_ to avoid those magical things like a plague, if you don't want or need them.
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).
Like I said, It becomes harder and harder to avoid it and that worries me. I used Laravel because anyone could just hop in and be productive.. I've asked myself why I'm not using just Symfony already, because I think Laravel is something that it's not anymore, or wasn't ever. Laravel is basically Taylor's view on how people should write code.
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
I get your point and this conversation might be as old as Laravel itself. I would like to point out a couple of things though:
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. ;-)
I have to admit, I'm still a bit biased against Taylor because of the Jetstream fiasco, but it seems it's getting harder to justify those feelings. Thanks for refreshing things.
Yes. But that is the case of all other tools and frameworks: a product devised by an individual's (or a group of individuals), opinion, taste and experience.
I totally agree and I hope they will remain external packages.
My workflow does not use/require any of them and I am happy as it is.
What it looks like Livewire is trying to solve is having a "reactive" way of doing things without touching javascript and by elimintating the need of implementing an API.
I understand the need of consolidating the dev process to one single language and siplify it but there is a reason why we separate backend and frontend.
I went down the rabbit hole of trying to minimize client side JS usage for web applications and interactions on websites with these kind of paradigms. I understand where it comes from and at first seems like a good idea. I tried prototypes, different libraries, tried to roll my own solutions etc.
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.
I feel like that sometimes but if you look at the open-source code and take time to understand it, it's not magic anymore but powerful abstractions. You could say the same about Laravel itself.
I don't argue with that. But the biggest problem is IDE integration. Too much magic and your IDE is becoming useless because it cannot autocomplete the most basic things anymore..
As a Laravel user, I agree with you completely. Laravel for API, Next.js/Nuxt.js to handle the frontend. It avoids depending on Laravel-<insert-name> frontend tool/framework/you-name-it.
Exactly, being able to pick your own frontend is what makes Laravel so useful to me. I hope they will give API functionality the same love and attention some day.
Swagger integration or something similar that generates documentation and live testing based on OpenAPI. Some support for endpoint versioning. Better ways to serialize models that have properties with computed values, on a specific request. ($_appends and $_hidden properties are getting a mess in complex projects). Plus, I'm sure people can up with more things I never knew I needed!
It's very different after the initial render. LiveView creates an Elixir process for each client which holds all of the necessary state, and then the client uses websockets to send requests and receive responses from that process. There's no rehydration done on the server-side, the state is kept in memory (by default. You can delete parts of it from memory but then you have to re-fetch it if you need it again). Requests and responses are absolutely tiny and you don't have to trust the client to send the current state, only the operation it wants to perform.
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.
Not sure what the OP is asking - if he's asking what kind of API or abilities they give you I would say pretty much equivalent things. If he's asking what the underlying architecture is then I yes they're different.
The server-side process in LiveView does enable some things that I don't think this does, like multiplayer games, collaborative apps and anything where you can have data/events made available to the client that doesn't originate from that client. One of the nice things with LiveView IMO is that it makes all of that work in the same programming model as the client sending things to the server and getting responses. It doesn't matter if the event originated from the client, some other client or eg. Phoenix Pub/Sub, it all looks and works the same.
I use Livewire quite extensively in production and it’s great. As someone that never got into Vue/React it has allowed me to build some pretty awesome and interactive UI’s.