8 ms·
HTML over WebSockets: real-time SPAs with barely any JavaScript
- deleted 2mo ago[deleted]
- thiagovsdiniz 2mo ago[flagged]
- ChiperSoft 2mo agoIs this satire? Rage bait? Why would you ever do this? Just make a normal website!! You've invented an MPA with extra steps!
- x0x0 2mo agoResponsive site built via server-side render, with a particular benefit for partial page updates. 90% of the benefit of an SPA but 10% of the code: no api, no moving of system of record for state back and forth between database and browser (it's always db), etc. And you can avoid react. A common use case: eg in Rails, a user has a table open. you can stream new records to the top of that table as they are created in ~5 lines of ruby (a broadcast on the model, and put the table rows in a turbo_frame with a turbo_stream_from somewhere on the page). There are real limits to this -- you have to hold the update dependency graph in your head -- but the benefits are huge for small to medium amounts of responsiveness. My experience has been great with Rails/Turbo and htmx.
- frollogaston 2mo agoI get how there's virtually no API if your client is simply rerendering the entire page each time it gets a ws message, but the article glosses over the partial page updates and just says "place the HTML where it belongs." How would that work? You'd need some kind of API for the client to request page parts and/or the server to tell the client where to place them.
- x0x0 2mo agono api. The way it works is thus (rails, because it's what I regularly use): The system is called Turbo. A turbo_frame is just a custom html element. You can largely use it instead of a div. Turbo's js watches for navigation events (link clicks, form submits) that originate inside one of these elements, and instead of letting the browser do a full navigation, it: 1 - makes the request itself, against the usual rails routes. It uses your normal routing, sessions, cookies, etc. 2 - Intercepts the html response and looks for a <turbo-frame id="..."> that matches the id of the frame that triggered the request 3 - Swaps just that element's contents into the page. more concretely: suppose I have a list of people in a flex table. I wrap the people table in a turbo_frame so I can prepend to it, and wrap each person in a turbo_frame so I can update it. My page can look as so: turbo_frame "people", class: "person-table flex flex-row" <-- the overall list turbo_frame person_1, class: "person-row flex flex-col" the row for person 1 turbo_frame person_17, class: "person-row flex flex-col" the row for person 17 turbo_frame person_12345, class: "person-row flex flex-col" the row for person 12345 etc. If the user edits a form for person 12345, that is wrapped in turbo_frame person_12345. The browser makes the request itself, grabs the response, pulls out the contents of turbo_frame person_12345 (and NB: the response can be a whole page or just this fragment), then swaps that in for the existing person_12345. It's designed so you can make your normal MPA with page navigations and reloads for editing a table row or whatever, make a small set of updates to the html, and have this work almost entirely for free. It sounds too good to be true but I've been using it for years and it often really is that easy. edit: for server-initiated updates, I can broadcast to select listeners: 1 - replace a turbo_frame (person_12345 was updated externally, and I want to just swap out) 2 - prepend (eg for a css table, put my new person_12345 row in front of other rows; 3 - append (same, but at bottom)
- frollogaston 2mo agoThis is kinda what I was expecting, but there is a whole library handling it for you. I just noticed the article mentions LiveView which probably does something similar.
- 2mo ago
- mikestorrent 2mo agoThen you'd have to focus on making a website someone gives a shit about, with content worth pursuing. Instead, one can just retreat into the engineering ivory tower, making an ever purer object that ever fewer people can understand or care about.
- hackingonempty 2mo ago> The quick rule: if you need bidirectional, low-latency communication (chat, collaboration, games), WebSocket; if you only push from the server, SSE is simpler and cheaper to operate. For most apps just use SSE and the built-in code for making HTTP requests (Fetch) instead of hacking up your own client side JS to make requests over a WebSocket. The latency is the same because modern browsers multiplex HTTP requests over a single TCP connection that is left open. Maybe if you are making many client requests per second there is an advantage to not sending full headers/cookies/etc... on each request but not if you're sending requests in response to user clicks/touches. Any sufficiently complicated SPA contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Fetch.
- clappski 2mo ago> The latency is the same because modern browsers multiplex HTTP requests over a single TCP connection that is left open. In my experience this isn’t true; firstly you’re relying on an implementation detail of the platform that you’re executing on, of which you have no control over on the client side. Secondly, even if you aren’t opening a new connection per request, you’re still travelling through an entire HTTP stack implementation rather than the incredibly simple WebSocket protocol - effectively a length and a mask to get the contents, rather than some (in http1 land) fuzzy parser. If you can guarantee you’re hitting http2 or http3 then you might be closer in latency, but due to the complexity of both I would imagine plain http1 negotiated persistent WebSockets provide the best latency.
- jallmann 2mo agoSure, but SSE connections in the browser - the typical use case - are persistent, so there shouldn't be frequent re-connecting. Unlike WebSockets, browser SSE also has a built-in recovery mechanism so you don't miss events across reconnects (`Last-Event-ID` header), although this does require explicit support from the server-side app. Given that the WebSocket handshake has an additional round-trip, SSE would typically be faster in terms of time-to-first-byte. > you’re still travelling through an entire HTTP stack implementation rather than the incredibly simple WebSocket protocol Both protocols have their own minimal framing, but "an entire HTTP stack" is a stretch. It's hard to argue that `data:value\n\n` is more complex than the WebSocket binary protocol. Simplistic, sure (no binary payloads), but also simple enough to, say, pipe through a regex. Good luck doing that with WebSocket.
- doublerabbit 2mo ago> Simple, elegant and fast. Until someone bombs your websocket server and you then have nothing at all.
- hyperhello 2mo agoWhat’s wrong with this idea, really? It’s redundant because you can serve HTML to requests with Apache or Ngnix or any other server on the happy path. What’s right with the idea, really? It’s exactly what the tried and true preferences of developers have been shown to be: getting in the way of the happy path for no reason. Now you can have build steps and put story points in Jira and do it all on the server where we don’t have to see it, and the success condition is that the text gets served. Both sides can be happy now.
- doublerabbit 2mo ago> What’s wrong with this idea, really? It’s redundant because you can serve HTML to requests with Apache or Ngnix or any other server on the happy path. Overhead, Security, Denial of service to name a few. You now have two states to track. Is the web-server serving the current version that the web socket is rendering? Is your monitoring enough? Is your monitoring going to detect if the web-socket server is suddenly taken offline? How do you monitor your web server is alive and ready to serve requests in the time of need? How do you determine if the socket server is actual offline and not frazzled itself in an event-loop? A stray network packet you never conditioned it for. If both your web-socket server and the web-server are going to follow the same source of truth for fail-over why not just use the web-server? The web-server is a tried and true method of serving websites. An application that allows you to easily load balance; tune and enhance with other security features. The best part is than you can actually serve a website without requiring JavaScript. Enterprise/corporate/country DPI firewalls like to silently block web sockets; any requests you're going to be rendering blank back to the client. Determining if the client is blocked isn't easy and how do you let the clients report an issue if they can't render the support page? The starting sequence of a web socket is an HTTP request header to an upgrade the connection. Correctly configured DPI firewalls block these upgrade headers so for all you know the connection has been made but the renderer fails silently. You still need a service to serve the JavaScript fronted so unless you create a WebSocket HTTP server which you've then opened a can of worms; you have a perfectly functional web-server sitting around idly wasting resources. As I bombard your web-socket server with faux requests slowloris style. Your web-server is alive and as far as it knows your socket server is alive too, how do you determine if the web socket is actually under attack? This adds more complexity in the mix. It's not wrong per-se. For a infrastructure learning exercise sure. However for anything else it's a waste of time and will cause headaches. The resources and the overhead for it all just isn't worth it. It's a mirage of something that looks opportunistic but isn't. Furthermore any alterations need testing on both parts. If you were to apply a hotfix for the web-socket side, does this negatively effect the web-server side? Does it perform the same way in Firefox and Chrome? If Firefox is slower at parsing the JavaScript html json, how are you going to accommodate that?
- nchmy 2mo agoA good response to this post https://yagni.club/3mstlyuxe5s26 https://yagni.club/3mstlyuxe5s26
- pseudosavant 2mo agoDefinitely a well reasoned counter point to choosing websockets over SSE.
- nchmy 2mo agoI forgot to link to OP's response to the response. It's mostly Ai slop. https://en.andros.dev/blog/bd74e61a/were-fighting-over-the-wrong-wire-websockets-vs-sse-for-html-over-the-wire/ https://en.andros.dev/blog/bd74e61a/were-fighting-over-the-w...
- cmoski 2mo agoIt's a better argument than the Datastar supporter's.
- sudodevnull 2mo agothe true irony is the article is about datastar, never change hackernews
- chrisweekly 2mo agoExcellent article. More compelling than TFA being discussed. Thanks for sharing!
- whitemoonx 2mo agoGod damn
- andros 2mo agoThe soap opera continues here: https://en.andros.dev/blog/bd74e61a/were-fighting-over-the-wrong-wire-websockets-vs-sse-for-html-over-the-wire/ https://en.andros.dev/blog/bd74e61a/were-fighting-over-the-w...
- deleted 2mo ago[deleted]
- pjmlp 2mo agoLove how DHTML, ASP.NET Ajax, JSF Ajax kind of keeps being re-invented.
- tclancy 2mo agoIndeed, “The initial learning curve is steeper than dropping in a <script>”. Maybe for you, but I was doing that basic thing in a mix of Django around 2010. It was getting away from traditional form POST and reload the page while still taking advantage of Django’s templating system. I keep trying to find the best answer to this approach across the things available as it feels like it would make vibe coding easier to manage and understand as well.
- noopydoopy 2mo agoExactly dear Lord we went the spa route for a reason
- pjmlp 2mo agoThe problem is that we went too far, and newer generations are now rediscovering the past.
- mikestorrent 2mo agoThe problem with the SPA is that the browser is a document platform being abused to run GUI applications. It's missing the core primitives that real UI platforms had in the 90s, like decent smart sortable tables and data bindings. So all that crap is redone in JS ten thousand times by developers of varying talents and the result is, has been, and will continue to be crap usability and hugely bloated sites. It's time to replace the HTML part of the browser with something else designed for purpose: making rich UIs that use platform-native widgets and mirror the human user interface design guide for the platform. XUL was a step in the right direction.
- Aeolos 2mo agoThe primary problem with SPAs is actually that the server state is duplicated client-side, which inevitably leads to state desync bugs. The secondary problem is SPAs approximately double the amount of code you need to write compared to a server-side approach for the same level of interactivity.
- deleted 2mo ago[deleted]
- frollogaston 2mo agoSo a RESTless webserver
- nchmy 2mo agoIn what way is it restless?
- frollogaston 2mo agoListed under advantages in the article: "State lives on the server. It is not memoryless request-response: there is a process per connected client that remembers where it is. It is the opposite of htmx, which is deliberately stateless."
- nchmy 2mo agobut if state lives on the server and all you are delivering is html, how is that not "restful"?
- frollogaston 2mo agoOne of the main properties of REST: "Each request from any client contains all the information necessary to service the request, and the session state is held in the client." In practice, REST makes things like caching, load-balancing, and debugging easier at the cost of needing to send more state back and forth. In HTTP, there are ways to reduce or at least hide the repeated TCP handshakes.
- alt227 2mo agoI dont get what you are arguing. If state lives on the server you have added complexity of holding state for every user. This is exactly what REST was designed to remove.
- frollogaston 2mo ago
- nzoschke 2mo agoClose but htmx with SSE and dom swaps and morphing gets you there without reinventing any wheels. Pretty much every web app I build has this pattern in it from day 1, as they all quickly expand to have a realtime inbox and notifications subsystem to support workflows and agents.
- nchmy 2mo agonow check out datastar for a smaller, faster, more extensible, more powerful version of that
- nzoschke 2mo agoI have tried it many times and I want to like it but I find the LLM doesn't program in it well. Maybe it's my fault, or maybe a model training, or something to improve in docs and SDKs?
- nchmy 2mo agoI was actually surprised yesterday the deepseek flash seemed to have some understanding of the datastar DSL. Also, you can pass this to the agent. https://data-star.dev/docs.md https://data-star.dev/docs.md
- Aeolos 2mo agoThe library is small enough I simply load the entire datastar codebase in the context when I need to ask how something works. Once you have sufficient context in your html, this is no longer necessary.
- NoDodgeQuestion 2mo agoIt would not be an htmx mention without mandatory nchmy datastar mention
- sudodevnull 2mo agoHTMX only does GET, doesn't to expo backoff, etc. Let alone the fact you need more extensions. Try it before claiming victory maybe?
- greymoonx 2mo ago[flagged]
- mattrighetti 2mo ago> Less traffic and less latency per action: a single persistent connection avoids repeating the TCP handshake and the HTTP headers on every interaction. You don’t need a TCP connection for everything. If you’re optimizing for that you can consider client-side caching which you can instruct using cache headers that every browser support. That usually reduces heavy hitters by a lot, even if you set the browser TTL to 1 minute which is fine for most of the scenarios.
- conradfr 2mo agoJust wanted to mention that in PHP besides Laravel Livewire there's also Symfony Live Components[0] [0] https://symfony.com/bundles/ux-live-component/current/index.html https://symfony.com/bundles/ux-live-component/current/index....
- j45 2mo agoLivewire existing and working so much simpler than the status quo really deserves attention.
- seanp2k2 2mo agoLeave it to PHP oldheads to continue to make dummy simple stuff that works well for decades. It's amusing to watch everyone reinvent everything every decade while the actual responsiveness of the UI that humans must interact with doesn't ever seem to get faster. Now we wait a few seconds for air vents in cars to adjust because it's all done with laggy, bloated software that was poorly-architected even though it has tens of cores and dozens of GHz of CPU and many many FLOPS of GPU behind it.
- j45 2mo agoI don’t use php much, I was recently researching a few parameters of how I needed an app to be structured and maintained, and after neutralizing any bias towards verbose or complex and brittle setups maintenance wise (which can happen with things like Javascript), it was interesting to see how many things popped up that were worth and work and maintain, after neutralizing the bias towards the rest. Simple scales, complex tends to fail. The livewire technology in Laravel though seems at least one order of magnitude simpler for the same baseline effectiveness or more that I’ve seen in many popular stacks.
- floodfx 2mo agoA few years back I wrote a backend implementation of the LiveView protocol in Typescript (https://liveviewjs.com https://liveviewjs.com) and played around with another BunJS-specific implementation (https://hotdogjs.com/ https://hotdogjs.com/). (Also did Java and Go versions but that's another story.) There isn't an official "protocol" so I had to figure it out by watching the WS traffic and determining how it worked which was fun if not tedious. That said, the more I learned, the more I was impressed by the efficiency and the programming model which felt simpler yet more powerful than SPAs. I did get to a point where I just got too busy to keep up and over the last couple of years things have changed a bit on the "protocol" side. But recently (a week ago-ish), I started poking at the old LiveViewJS repo with the help of coding agents. Now that Phoenix is past 1.0 and the JS runtimes (Node, Deno, Bun) have more overlap in terms of APIs and library support, I think it will be more straight forward and frankly easier to get and stay at parity.
- wetpaws 2mo ago[dead]
- aitchnyu 2mo agoI like the Vue/React/Svelte model of the DOM being a function of the data. For example, in a shopping cart, I add two chocolates, the number against the chocolate, the count at top and a banner encouraging me to reach X total all center around a data structure. I use Django Ninja, Zod, InertiaJS+Vue and its as easy as using Django's templating engine, but static typing ensures my view doesnt emit unrepresentable data, my TS doesnt accept unrepresentable data, Vue+TS dont allow logic errors in template. AI makes it effortless. Again, the loaded page is a function of the data supplied at the view. With HTMX, I'm writing several server-side functions to mutate the DOM imperatively and using HTML attributes to call them. Its great for forms but that shopping cart example needs code scattered across multiple functions and templates.
- MrBuddyCasino 2mo agoYes I don’t see the appeal of HTMX in most cases. Vuejs has less footguns than React, and LLMs can produce it decently well to at least get started and then refactor.
- llbbdd 2mo agoThe appeal is that it's not React, aimed mostly st people who have a grievance against React for one ill-informed reason or another. In time it will either become React by another name or die out.
- mikestorrent 2mo ago> Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.
- llbbdd 2mo agoAbsolutely. Show me the source of a sufficiently complex web application that isn't built on React, and I'll find the React-by-any-other-name inside.
- 2mo ago
- egeozcan 2mo agoThis gives me too much <script runat="server"> or even JSF vibes.
- noopydoopy 2mo agoThey keep trying to reinvent webforms, bleh
- odig 2mo ago[flagged]
- deepsun 2mo ago> Place the HTML where it belongs Well, some drawbacks are not accounted for when replacing HTML parts: input elements lose focus, if some view was scrolled, then it gets unscrolled, jumping under user's pointer etc.
- cmoski 2mo agoI don't recall encountering these issues. What framework was that on?
- sudodevnull 2mo agothings like datastar handle this automatically for you
- austin-cheney 2mo agoHTTP over WebSockets: Sounds like the same tag line I have been using in my project for the past 2 years. https://github.com/prettydiff/aphorio https://github.com/prettydiff/aphorio My approach is pretty simple. Since the connection phase of WebSockets is RFC2616 compatible, per RFC6455, you can use the same server logic to connect both.
- carllerche 2mo agoTopcoat (Rust) is aiming taking this approach as well: https://github.com/tokio-rs/topcoat https://github.com/tokio-rs/topcoat. The project is still in the early days. It won't require WebSockets, but WebSockets will be an option.
- goatlover 2mo agoIs Meteor.js still in use? I recall early on it was all the rage, but that didn't last too long. I had thought it delivered updated html over sockets, but maybe it was just the data. Did seem to be a bit more of a heavy JS framework, but it's been years.
- vlasky 1mo agoOn the contrary, Meteor.js is alive and well! Version 3.5 was recently released with major performance and scalability enhancements: https://forums.meteor.com/t/meteor-3-5-is-out-change-streams-performance-improvements/64461 https://forums.meteor.com/t/meteor-3-5-is-out-change-streams...
- mircerlancerous 2mo agoFrankly I think serving dynamic HTML at all is a problem in an SPA. Use a service worker to cache structure, control, and styling, then use an API to fetch dynamic data in a more efficient manner.
- dalemhurley 2mo agoWe have come full circle.
- altairprime 2mo ago> that loose back-and-forth over HTTP weighs more than an always-open WebSocket This is definitely true for HTTP/0 and /1. Is it still true under HTTP/3, or has the underlying ‘single conduit, many channels’ model improved things if used correctly?
- Aeolos 2mo agoAbsolutely not, even on HTTP1.1. Our webapp is achieving 800:1 to 5000:1 compression ratios pushing down the entire HTML page over brotli and zstd. The first render is about 20:1 compression, every interaction after that is 800-5000:1. We are using datastar with the recommended "fat morph" approach where we re-render the entire HTML page from scratch on every request. Our typical RTT is <100ms including rendering, then the brotli / zstd compression window cuts down the wire size to literally _bytes_. This is SO much more efficient than our previous reactjs & graphql render waterfalls with state duplication in the client side. All states lives on the server, all renders are authoritative, and we need to maintain roughly half the code size for better first-render and massively better interactive performance. Appserver and DB pressure is massively reduced too. (This is a medical device with a highly interactive UI, image viewers, editors, not a boring old static website.)
- altairprime 2mo agoOkay, so, to parse this — you have a highly performant http/1 app using a fresh connection setup/teardown at 100ms per cycle? Have you tested that same app over http/3 with tuning to reuse the underlying channel, and if so, what were your outcomes? H1 can be pretty awesome but my core curiosity here is whether reducing the connection overhead through H3 matters or not. I am not out to disprove H1 full-page HTML as a delivery mechanism.
- Aeolos 2mo agoWe are serving over HTTP/2 and currently testing HTTP/3. I don't have direct HTTP/1 vs HTTP/3 comparisons, because 0% of our requests are over HTTP/1 today...
- bluerooibos 2mo agoMeh, just use Rails and Hotwire.
- isomorphic- 2mo agoAllowing unmoderated real-time chat with all visitors is certainly a decision.
- xutopia 2mo agoFunny he mentioned Chris McCord as the originator of this technique with Liveview. The reality however predates that with Sync in Rails that you guessed it... was also Chris McCord's doing. Rails at the time didn't have the capacity to handle it so it was just a tech demo then and a big reason why Chris McCord moved to Phoenix. He was once a prolific Rails developer. That guy is helping the web move forward.
- ricardobeat 2mo agoWe were also doing this at Booking.com many years earlier, using morphdom and custom templating libraries. I think I wrote the first version in 2014-2015.
- ilumanty 2mo agoWhy did you stop doing this? What was the successor?
- xutopia 2mo agoToday's Rails has https://hotwired.dev https://hotwired.dev and it's built-in. I've used it on quite complex UIs and for the life of me I don't believe React would be so popular in new projects if people knew how good this was.
- ricardobeat 2mo agoThere were some hard problems related to legacy systems that made it hard to provide the best possible DX; eventually the influx of React devs was too strong to hold - adoption started in 2020 IIRC.
- noopydoopy 2mo agoWas predated by Microsoft with web forms.
- josefrichter 2mo ago[flagged]
- animitronix 2mo ago[flagged]
- simon84 2mo ago> What are its advantages? > There is only one rendering engine, cutting down complexity. Actually there are 2 rendering, the server sending HTML and the browser drawing it on your screen. So why not push the logic and send a jpg image of the rendered content itself. Lol The whole concept of decoupling the frontend and the backend is that they can be agnostic of each other, they need to align but it is not the same skills/concerns. Serve rendered html like in 2000 and you have recreated a smart way to do what industry spent decades running away from.
- mikestorrent 2mo agoThere are proxies to enable old computers with old browsers to render the modern web as an imagemap. And of course, 20 years ago I was doing everything you'd want to do with a modern webapp with PHP; fast enough for a thousand users on a dual CPU Xeon.
- jdkoeck 2mo agoAccording to your logic, front end apps thus have three rendering engines: the server (rendering json), the browser, the JavaScript framework. Count the rendering engines like you want, the point still stands: server rendered apps are architecturally simpler. There is no one size fits all solution. Frontend-heavy projects have their place, server-rendered ones too.
- 3dedb728-3f77 2mo agoAll of this to finally come back to old web with html generated on server. It make me happy.
- socketcluster 2mo agoReading this is especially interesting to me because it's what I've been working towards for the last 14 years or so. Though like this group, it also came together for me piece by piece. I got interested in this specific idea back in the early days of Firebase I saw someone built a realtime HTML component with PolymerJS called 'collection' and I became consumed by the idea of fully generic realtime self-updating components. My approach is a bit different than OP or that of HTMX though; it's JSON over the wire, not HTML. I've built a full implementation in Node.js with a set of declarative frontend components. https://github.com/Saasufy/saasufy-components?tab=readme-ov-file#saasufy-components https://github.com/Saasufy/saasufy-components?tab=readme-ov-... And https://saasufy.com/ https://saasufy.com/ I'm thinking to make open source. It's nice to see major frameworks coming to a similar conclusion.
- zemnmez 2mo ago>Safer against injection: since the server renders and escapes the HTML before sending it over the channel, an attempt to sneak in a <script> travels as inert text and reaches your neighbor's screen as plain letters, not as code. The same architecture that makes a chat trivial makes it immune to XSS. I strongly disagree with this point, and in general I've seen the reverse is true. Only the client truly knows how it will interpret especially esoteric kinds of html tags and relying on the server for sanitisation is relying on the system furthest from the authoritative renderer.
- gwbas1c 2mo agoA lot of the people who oppose this technique don't understand context: The right solution to your problem often involves understanding the problem you're trying to solve! In my case, I work on two Blazor websites: One is standard in-browser WASM with Restful JSON (and some CSV) over http; the other is server-side Blazor that uses the websocket technique that this article describes. The server-side Blazor approach is for an internal web application that has a lot of quick-and-dirty pages that replace what used to be ad-hoc database queries and ad-hoc scripts. It's not an "industrial strength" web application that requires high scalability, because it's only a handful of employees who use it. It's also a joy to work with. To be specific, we don't need to go through the exercise of designing an API, making sure that contracts serialize, ect, ect, just to slap a UI around what used to be a script. The WASM page that uses Restful JSON (and csv) is our customer-facing web application: JSON (and CSV) help with debugging; but the cost of making an API is very high. Development on the customer-facing web site moves much more slowly, but it's "worth it" for an industrial-strength site. Would I build a highly scalable website using HTML over a websocket? Maybe. The issue is time to market: Because you don't have to build an API, you can move faster; but I don't know if scalability issues will arise.
- avgDev 2mo agoI also use blazor server for internal web apps. It is fun to work with and development is quick for a C# dev.
- pjmlp 2mo agoWhich kind of proves the point I made elsewhere about ASP.NET Ajax, as Blazor in spirit is a kind of WebForms 2.0/Silverlight.
- gwbas1c 2mo agoHonestly, I didn't do much with webforms other than a "Hello World" project. I hated it; fortunately at the time my paid gig was Winforms. (C# Desktop.) Webforms just hid too much of "the web" to be useful, IMO. Silverlight required a proprietary browser plugin. I wouldn't touch it with a 10-foot pole. Blazor (server-side) doesn't hide the web; although if you need to do things that are "close to the wire"; you should either use the WASM variant or a different stack. Remember, I use server-side Blazor for things that would be ad-hoc queries or scripts, and it's for a website that only a handful of employees use. I'm not sure how it would handle an "industrial strength" massively-scalable application. (At least in that situation, most of the code will port nicely to WASM so you do have an exit strategy that doesn't require a whole rewrite.)
- coreyp_1 2mo agoI hate modern web development. I was a Drupal developer back in the day, and I loved its templating system (the fact that HTML was assembled on the back end) and it was so powerful! It allowed for so much customization without leaking the internals of your representation to the front end, which was much more secure, IMO. Now, you have to give your templating logic to the client and potentially expose parts of your system to the end user. Then, along comes MVC, and everyone drank the Kool-Aid, despite the fact that nobody ever actually implemented MVC purely, because it wasn't designed for the web. It wasn't designed for general systems, either. You may say, "you're wrong! You can adapt any system to MVC!", and I would respond that that is not what I mean. I mean that it is designed for custom applications (what you are referring to), and not frameworks which are for general use. You might claim that it is a framework, and I would point out that the nuance is in where the customization can be controlled and distributed. (Side note: I know MVC has been around a long time, but so have I and I remember when ajax was the hot new toy. MVC took a long time to gain traction and to infiltrate everything... and now we have ultra slow websites with tens of megabytes to download before they can even show a blank page. I stand by my statements and distain for MVC.) I was building my own CMS that went back to server-side rendering, but I stopped because I just didn't have time to work on it. This may inspire me to do it again, only this time I'll use an LLM to get me through it faster.
- exodust 2mo agoPlease revisit your CMS idea. They're still around, like Kirby and others. You are right about the old templating systems. I still use them. I still use PHP, it's ridiculously fast and mature. It has a readability unmatched by other languages (for devs like me with design background). I'm surprised to hear CS people like yourself talking up the old templating systems! > I hate modern web development. For me, modern web dev is about modern CSS and JS and native browser APIs and all that fun stuff. It's ironic now with LLMs, the people caught in the grinding gears of MVC bloat are benefiting least from LLM. Well, perhaps I can't make that claim, but the point is LLMs do a fantastic job at focused, single-layer arrangements such as the good old templating systems, vanilla JS and just direct "old school" frontend coding. Why burden ourselves or the LLM with truck loads of layered dependencies or a million steps to hello world? No need but people get angry on this topic though, so I just do my thing in my corner of the web and deliver results for those I build for.
- cbsmith 2mo agoEverything old is new again. ;-)
- TacticalCoder 2mo agoInstead of fighting about which of the three options highlighted in TFA: HTMX (or Unicorn etc.), SSE or Websockets is "the best" I think we should take time to be extremely thankful that... At long last we've got very serious contenders actually catching on that have "barely any JavaScript" (TFA's words). We switched to SSE and couldn't be any happier. Any tech that allows to reduce the need to reach for JavaScript on the frontend is a godsend.
- insane_dreamer 2mo agoAre we coming full circle? I feel like I was doing this with Ajax 15 years ago ...
- felixding 2mo agoI used all of them in various projects: "traditional" Ajax-based SPAs, HTML over WebSockets/SSE, etc. Then I found Inertia.js and never looked back. With Inertia.js, you get the real feel of an SPA without the complexity of maintaining APIs just for the frontend. You can even make some pages plain HTML (like the homepage, legal pages, etc.), while making pages that require reactivity SPAs.
- songhonglei1985 2mo ago[dead]
- 1vuio0pswjnm7 2mo ago"Was Top 7 on Hacker News" Contrast with something like "had 7th most comments on Hacker News" Consider (a) algorithmic ranking, (b) votes and (c) discussion, i.e., comments, aka replies Perhaps in some cases (b) might drive (a) which then drives (c), and of course (a) can drive (b) As such, (b) votes and (a) ranking are almost always aligned However, (b) votes and (c) comments are not always aligned For example, comments with large point accumulation, i.e., votes, and hence high ranking, usually receive some negative replies (source: personal experience) This can also be true for submissions gaining points rapidly
- cpill 2mo agofor normal web stuff this is bananas. for an online, multiplayer game it would be awesome!
- hahahaa 2mo agoPerfect. If you live in a city, this is deployed to the edge, you have a low latency, fast, unmetered connection and run a M series mac or decent PC.
- mcintyre1994 2mo agoLiveView can send less data than a JSON API, and the client has less work to do.
- mcintyre1994 2mo agoSomething else that I think is interesting here is the new HTML streaming APIs in Chrome: https://developer.chrome.com/blog/declarative-partial-updates#out-of-order_streaming https://developer.chrome.com/blog/declarative-partial-update... These mean that you can for example have a websocket serve just the new HTML, and then let native browser code figure out inserting it into the DOM, without any dependency. I’m guessing things like LiveView could eventually migrate to this if it becomes standard, and eliminate more of their JS bundle.
- bob1029 2mo agoI know the point is to minimize JS here, but have we ever considered sending raw JS over the socket? JavaScript can be a lot more compact than the final DOM that it affects. Dynamic JavaScript is much more interesting than dynamic html. SSR HTML is a boring, solved problem. I need something more exciting in my life these days.
- nchmy 2mo agoI can't tell if you're being serious or not... It's either top tier trolling or you're a lunatic
- deleted 2mo ago[deleted]
- deleted 2mo ago[deleted]
- red_admiral 2mo ago> the server sends the HTML already built and the client just places it where it belongs Mind blown. A much bigger pet peeve of mine is making a SPA when a bunch of HTML pages would do, and would give you sensible URLs and the ability to open more than one tab in the first place. When you actually need a SPA, I'd only go websockets if I really need that low latency and your clients are close enough in the first place, if they're half the way around the world on a slow connection you have different design constraints. A chat application works just fine over SSE or similar. Client-initiated requests even work with plain old fetch().
- radarsat1 2mo ago> It is not memoryless request-response: there is a process per connected client that remembers where it is. It is the opposite of htmx, which is deliberately stateless. This reflects some misconceptions I had about websockets before I used this protocol in a real application. In practice I found the following to be true: - Connection can drop at any time, be ready to reconnect, don't depend on that happening on the same server as before. - Messages may arrive out of order due to how framing works. Many implementations will complete a shorter message before an earlier longer message finishes. Don't depend on stream order for a one request-one response style messaging. Yes it's a serial TCP stream but it's basically modeling an asynchronous message protocol on top of that. This is reflected in the browser side API which just provides "onmessage" and leaves it up to you to track state. What this boils down to is that it's great for latency (but arguably superseded by WebTransport), but ultimately you're best off using it to handle a stateless protocol just as you would HTTP requests. If you do maintain state per connection, that state should only be metadata about that connection, such as a connection-level request id, or the caching of some contextual info (eg. user id) to avoid repetition in future messages. So I usually consider it a transport-layer optimization rather than something my application fundamentally depends on. At the end of the day with HTTP/2 reusing open connections combined with SSE, you should be able to achieve essentially the same behaviour and even latency. It's still useful to support but I disagree that the transport should dictate the framework style here, they are simply different layers that shouldn't be concerned with each other.
- eleumik 2mo agoAlmost. Is links or hypermedia the point not web sockets
- orishlez 2mo ago[flagged]
- hackmack10 2mo agoSo basically, this entire conversation and article is summed up by 6 in one hand and a half dozen in the other in regards to this method vs traditional SPA's.
- xtiansimon 2mo agoHaving a hard time following the debate—all I want to know, is there a particular use case which makes websockets seem so attractive? A particular network topology?
- gregoriol 2mo agoIt would be nice if it was easy to "place the HTML where it belongs", but in a complex app it's never just-replace: you have to preserve a lot of state, wether it is filters, forms, user selection, scroll position, ... so updating live becomes quite a huge work. I've seen good attempts with libraries like idiomorph, but still quite some plumbing to do depending on the app.
- chunkydev 2mo agoI was wondering: Suppose it would be possible to do this with just a normal HTTP requests and create a real-time SPA by keeping an connection open and doing POST requests from I-Frames. I'm absolutely positive that is possible. No javascript, websockets, or SSE, only HTML and CSS and backend logic. Would this be interesting or inspiring to anyone, apart from users who'd rather not allow javascript in their browser?
- sceptic123 2mo agoHow does this mean you don't need an api?
- bobbylarson 2mo ago[flagged]
- centuryfall 2mo agoOn a side note, this is possibly the prettiest dev landing page I have ever seen.
- centuryfall 2mo agoI’m not understanding how websockets fixes the issue of pushing JSON to the client side for it to be rendered into HTML. JSON is just a data object can translate into text to place in the HTML document. Moving this to the backend with a templating engine still requires a formatted object, correct? I like SSR rendering, but I think the diagram with websockets is missing a key step, where the database results still need transformed into a consumable format that gets plugged into the templating engine. That step can’t get eliminated with either model. Regardless of where the document is built, it needs to consume some format of structured data. Am I missing something?
- lexicality 2mo agoI remember doing this with jQuery's $.ajax nearly 15 years ago. This seems comically overcomplicated in comparison. Why bother with the overhead of a websocket? > You do not need to build an API: the server generates HTML and sends it to the client, with no middleman. You're still building an API, it's just inside the websocket handler rather than http. Essentially this is yet another DIY RPC framework. Why reinvent everything yet again? jQuery still exists. All the required methods still exist too. You can build a bog standard HTML website and then use progressive enhancement to fetch the next html page and replace the content of the current one with that, which has the benefit of handling middle click perfectly.