If Not SPAs, What?
macwright.com
macwright.com
When SPA's became the norm and even static web pages needed to be build with React, developing became more and more inefficient. I saw whole teams struggling to build simple applications and wasting months of time, while these used to be developed within a couple of weeks with just 1 or 2 developers, on proven server side opinioated frameworks. But that was no longer according to best practices and industry standards. Everything needed to be SPA, micro services, distributed databases, Kubernetes etc. These components and layers needed to be glued together by trial and error.
I am really happy that common sense is starting to return and more developers are starting to realize that integrated end to end frameworks are very useful for a lot of real life application development scenario's.
I'm in a weird situation where I'm contracting into one organisation and they've contracted me out to another. The first organisation know me as a senior dev/architect with 15 years experience in a niche domain. The second organisation see me as brand new to them and despite paying an embarrassing day rate are giving me noddy UI tweaks to do. Extracting myself is proving to be slow somehow.
Anyway, they wanted a webapp with a couple of APIs and nothing on the page than a button, the authenticated username and a line of text. Clicking the button opts you in/out of a service and the text changes depending on the state. The sort of thing people go to once, maybe twice.
I used a mustache template on the server side to populate the values and I didn't even bother with any javascript, just did an old school form submission to the API when the button was clicked and a redirect back to the page.
It was tiny but, obviously it was decided "we should be using a more modern framework" - code for React. It was the more word that got to me, as if there was an equivalent, dated framework I'd used. I didn't put up a fight partly because I was new to the team and figured they were hot on React and I wasn't. Somehow, they made a complete hash of it, they couldn't even figure out how to get all their inline styles (the only styles they used) working without help.
I guess it's just those classics; people want to learn the hot new thing as they see it, their managers are happy that they've heard a buzzword they recognise and then everything becomes a nail for their new hammer.
It seems to me what we want is some kind of "Platonic ideal" where the extremes are bad for development:
Management won't give us time to deal with technical debt/incorporate best practices.
|
|
THE IDEAL
|
|
Management wants the Hot New Thing all the time. uservices are the state-of-the-art in best practices so uservices it is!
The best advice (IMO) in dealing with the top end of this spectrum is to frame technical debt and best practices in terms of whatever economic metric the manager cares about (e.g., "TDD will lead to less bugs, ergo happier customers, ergo greater retention"). But I wonder if the same framing can be used to encourage temperance in managers who dwell on the bottom of my spectrum.I somehow suspect it won't work. The problem with those at the top is that they see the dev's proposition as an investment that will either not bear fruit or, worse, slow the team down; so they are incentivized to keep status quo. Those at the bottom, however, start from a perspective that their idea will add value to the team so they keep pushing for it no matter what. And telling them "Let's not do what Google does; we're not Google" is definitely seen as a devaluation of the team.
This has been a weird headspace to explore. I'd love to hear from others' experience on dealing with this.
Management that don't really understand tech and is afraid to try things
|
|
THE IDEAL
|
|
Management that don't really understand business (and sometimes tech too) and is focused on tech fashion
Surprise the ideal is hard because it requires both tech and business experience to recognize how best practices and new tech could bring value in a specific context. The job is to make clients happy by solving their problems, with apps that are nice to use, bug free, performant, maintainable, evolvable, with a usually short time to market and obviously for the best cost. Sometimes that equation is solved with a complex stack, architecture and practices with hundreds of engineers, and sometimes with a few web pages, inlined CSS, a bit of vanilla JS, and a solo dev.I mean it'll only take them an hour or two to write it up, better to spend that than the 20 hours it would take you (for example) to spin up a new stack.
Anecdotally I find the opposite to be true. I've been writing frontend code for over a decade, but I've never moved faster and wrote less buggy code than now. Is that because I've become a better developer? Sure, a little bit. But by and large, I don't believe that ultimately is the reason. I think it's the maturity in the technology. My growth as a programmer is hardly linear and the past 5 years have not matched the growth I achieved in my first 5. Frontend tooling has never been better than it is today.
What I believe, is that the bar to build web applications has been lowered, and there are more programmers than today than ever before. You have people who are not experts in frontend development and javascript trying to build complex UIs and applications. So you take this person who doesn't have the requisite experience and put them to work on a paradigm with a lot of depth (frontend) using frameworks that are really simple and easy to get started with, but compound problems as they are misused.
Another factor is that since SPAs are stateful, complexity mounts aggressively. Instead of a refresh on a stateless page every few seconds, one page causes bugs that rear their head for the duration of the session. These inexperienced people are put in charge of designing codebases that don't scale and become spaghetti. But when designed properly, these problems are largely negated.
I'm not advocating that SPAs are the solution to all problems. I think there's gross overuse of SPAs across the industry, but that is not an indictment of SPAs themselves. That is someone choosing the wrong technology to solve the active problem.
With respect to angular (1, I never touched 2) specifically, I always found it extremely overengineered, poorly designed, with terrible APIs. But that's a problem with that specific framework and says nothing at all about SPAs at all.
What's the library or design pattern to consume a REST API in React or any of the mainstream front-end frameworks? The only thing I'm aware of is Ember Data but Ember is apparently not cool anymore, and I couldn't find a suitable replacement.
I'm asking because in all the projects I've been involved with, consuming the backend API always felt like a mess with lots of reinventing the wheel (poorly) and duplication of code. I can't believe in 2020 there's not some kind of library I can call that will give me my backend resources as JSON and transparently handle all the caching, pagination, error handling (translate error responses to exceptions), etc and people have to do all this by hand when calling something like Axios.
In contrast, Django REST Framework handles all that boilerplate for me and allows me to jump right into writing the business logic. It's insane that ~30 lines of code with DRF (https://www.django-rest-framework.org/#example) gives me a way to expose RESTful endpoints for a database model to the web with authentication, pagination, validation, filtering, etc in a reusable way (these are just Python classes after all) but the modern front-end doesn't have the client equivalent of this.
If you look at 20 REST API's you'll probably see 30 different patterns for pagination, search/sort, error responses, etc. There have been a couple attempts to standardize REST such as OData but I think it's safe to say that they haven't been very successful. It's kind of challenging to build standard reusable front end tools when everyone builds back ends differently.
For React, its out of scope; anything that you can use in JS for this can be used. If you are using a state management library, that's probably more relevant to your selection here than React is.
REST is also too open-ended for a complete low-friction solution, but, e.g., if its swagger/openapi, there's tools that will do almost the entire thing for you with little more than the spec.
> The only thing I'm aware of is Ember Data but Ember is apparently not cool anymore, and I couldn't find a suitable replacement.
Ember Data is definitely a valid choice. It may not be hyped right now, but that has little to do with utility or use in the real world.
My team generates backend stubs from our GRPC spec which allows us to jump right to implementing our business logic.
Frontend projects make use of the GRPC-Web client codegen to make calling the API simple and type safe (we use typescript).
We mostly use all the official GRPC tooling for this. We write backends in golang and dotnet core so GRPC-Web is supported quite well out of the box.
I wrote a slightly modified Typescript codegenerator to make client code simpler as well: https://github.com/Place1/protoc-gen-grpc-ts-web
I think this is one area where front end tooling can be painful for the average dev. The bar to writing idiomatic JS for a given framework can get pretty high quickly, especially when you look at some of the really popular tools out there (i.e. redux).
Front end work has become so much harder to grok because the patterns around things like state management still have a lot of warts. The terminology of redux drives me crazy because it’s really difficult to explain things like reducers.
A redux reducer: The action and the current state reduce into the new state. And of course it doesn't matter how many reducers or combined reducers your state uses - they're all ultimately just doing this.
This also works for Array.prototype.reduce(). You're reducing two things into one.
I'm primarily a backend developer and I think in general backend developers makes for "poor fronted devs". I'm talking about those "occasional" times the backend-dev needs to do some f.e dev work. Just because they don't know the tech as well, best practises and spend as much time with it as a dedicated F.E Dev. jQuery code written by the "occasional front-end dev" is kinda horrific in many cases.
Now please internet hear me. I'm not saying you can't write bad code in a JS-Framework. I'm saying it's usually less often and less bad - especially for non-dedicated f.e devs
Like crossing a street, just looking left and right won't guarantee you to be safe in your crossing, but it damn near makes it less probable.
If you are a shop with mostly backend-devs and don't want to invest in a F.E dev, you definitely should look into a js-framework.
*Svelte is always good start very small and bare bones.
That matches in my experience.
I worked in a shop with only backend developers and the frontend was an absolute buggy mess of jQuery on top of bootstrap. After migrating most of it to Vue I taught it to the team and all the experienced-but-frontend-shy developers started producing great frontend code by themselves.
I second this
The barrier to entry is lower than for React, and the results are great
eh. Swing in its golden age run circle around what we have now. Granted it's old tech now that we settled for in-browser delivery, but still:
- look and feels could do theming you can only dream of with css variables/scss
- serialize and restore gui states partially or whole, including listeners
- value binding systems vue can only dream of
- native scrollers everywhere you could style and listen to without the rendered complaining about passive handlers. - layout that didn't threw a fit about forced reflows
- unhappy with the standard layouts? build your own one as needed
- debug everything, including the actual render call that put an image where it is
- works the same in all supported os
browsers are an insufferable environment to work within compared to that, css is powerful and all but you get a system you can only work by inference, and were everything interferes with everything else by default, which works great to style a document and is a tragedy in an app with many reusable nested components.
There are a few things I definitely miss from my 20 years as a Java dev, but the half assed and under funded Swing UI is not among them.
Give me HTML+CSS+JS any time.
Yes, the bar to build web applications has been lowered. We can all build something on the level of GMail now.
The ability to build websites has been crippled, because you are often forced to build the sites using the tools suited to applications. As you and both the parent comment seem to agree on.
This is a major problem with our industry. Unfortunately, the people with the power to curb this trend have their paycheck depend on it continuing.
As a company, you are incentivised to have a large tech team to appear credible and raise funding, so you hire a CTO and maybe some engineering managers. Their career in turn benefits from managing large amounts of people and solving complex technical problems (even if self-inflicted), so they’ll hire 10x the amount of engineers the task at hands truly requires, organise them in separate teams and build an engineering playground that guarantees their employment and gives them talking points (for conferences or the seemingly-mandatory engineering blog or in interviews for their next role) about how they solve complex problems (self-inflicted, as a side-effect of an extremely complex stack with lots of moving parts). Developers themselves need to constantly keep up to date, so they won’t usually push back on having to use the latest frontend framework, and even if they do, that decision is out of their hands and they’ll just get replaced or not hired to begin with.
In the end, AWS and the cloud providers are laughing all the way to the bank to collect their (already generous) profits, now even more inflated by having their clients use 10x the amount of compute power that the business problem would normally require.
Maybe the issue is the seemingly-infinite amounts of money being invested into tech companies of dubious value, and the solution would be to get back to Earth as to have some financial pressure coming from up top that incentivises using the simplest solution to the problem at hand?
It just takes years and lots of room to do basically nothing, and if something meaningfully shifts, you need a while to get back up to speed.
I'm not saying it's efficient, or that you should dive in, but I did want to throw out there that there is a light at the end of the tunnel. People using React.js aren't flailing about in the dark the whole time.
I'd rather have their architecture than 100's of VMs.
Hell I might even run kube if I was running bare metal. Declarative workloads are amazing.
It sounds crazy to say that now but Angular became big because it was actually quite lightweight compared to other JS frameworks of this era, declarative 2 way databinding was cool, it was compatible with jQuery (thus its widget ecosystem) and it was also developed with testing in mind. So it was easy to move jQuery projects to Angular ones, and developers cared about this aspect and it helped organize code quite a bit. Angular 2 on the other hand never made sense and it was a solution looking for problem.
React and JSX came along and allowed developers to use JS classes when a lot of browsers didn't support them. And unidirectional dataflow was all at rage. It was always the right solution of course, but I never heard about DOM diffing before that which to me is the main appeal to React. To this date, HTML API still do not have a native(thus efficient) DOM diffing API which is a shame.
> When SPA's became the norm and even static web pages needed to be build with React, developing became more and more inefficient. I saw whole teams struggling to build simple applications and wasting months of time, while these used to be developed within a couple of weeks with just 1 or 2 developers, on proven server side opinionated frameworks. But that was no longer according to best practices and industry standards. Everything needed to be SPA, micro services, distributed databases, Kubernetes etc. These components and layers needed to be glued together by trial and error.
IMHO the problem isn't React and co or even SPA. In fact writing an REST/Web API should be easier than writing a server-side generated HTML website (no need for templating language, ugly form frameworks,...). The problem is the horrible and complex NodeJS/NPM backed asset compilation pipelines and build tools that these framework often require in a professional setting, which incur a lot of complexity for very little gain.
Why is that easier? It's more work, you are now rendering two views instead of one, a JSON one(server) and HTML one(in the client) with all the JSON encoding/decoding that it entails. You are still using a templating language and, dealing with forms in React is more cumbersome than doing it server-side.
Nitpick, but I doubt that was the reason developers are flocking to React back then. In the beginning browsers didn't support JavaScript classes and neither did React. You fake them by using a function known as React.createClass instead. There was also no transpilation required, as JSX was optional. In fact React was always about unidirectional data flow, and reasoning about state -> DOM elements rather than reasoning about changes to the DOM.
Would like to hear more.
To get a job, devs need experience in relevant tech. No company is willing to train their devs - they all have to hit the ground running. So devs have to have demonstrable experience in the tech that lots of companies use. Companies need to hire devs, and don't really care what tech is used. But using what everyone else uses makes their hiring easier because it's easier to find devs who want to work on that tech. So they advertise for devs with experience in a hot tech. The devs see this and try and move their internal projects to use the hot tech so that if/when they look for their next job they'll have experirence in it.
The devs are just trying to stay relevant in a rapidly changing tech scene so they can get their next job.
The companies who employ them don't care what tech is used, but find recruiting devs to be easier if they're working in the latest hot tech.
The key point that could change all this is if companies were willing to train their devs in the tech stack they're using.
To be willing to not use an SPA, you need to be willing to exclude certain options from day 1. Find me a product manager willing to do that.
How many times has it actually happened that some scrappy startup has 1) became the next big thing and 2) not being at the edge of over-engineering actually killed it or significantly impacted its revenue? This just feels like wishful thinking.
Also keep in mind that even if you were on track to become the next Google Docs, this means your current product is usually good enough as-is and gives you time (and $$$) to improve it.
IMO when the time comes and your product is used well, you may be ready financially and technically to do a complete rewrite. Otherwise maybe the current functioning application is better if the rewrite isn't justified.
Angular is a giant confusing pile of magic. It's so complex you've gotta be a core developer to even understand how an app comes together. Stay the hell away if you can
This course is a pretty great intro: https://pragmaticstudio.com/phoenix-liveview
One interesting thing is that it makes you consider memory issues again since all your rendered data structures are held in memory in the LiveView process unless they are explicitly cleared after the render with "temporary_assigns". For apps that would have to hold and transfer a lot of data up and down the channel I've ended up using a hybrid of LiveView with divs set to phx-update="ignore" in which I mount React components.
In practice, I've usually found that the advantages outweigh the disadvantages when it comes to the former. Beefing up my servers seems like a worthwhile trade-off.
When it comes to latency, or related issues, I find that I'm still so much better off using LV as a basis and 'dropping down' into plain JS or (p)react when I need it.
We recently delivered a project that involved a whole bunch of stuff that LV was a perfect solution for, but also a core bit of functionality that required various kinds of animations. We ended up using LV wherever we could, and piggy-backed on the LV channel (websockets) to handle synchronizing the animation stuff. The actual code to animate things was just plain old JS. Worked like a charm!
There are so many tradeoffs present that happen to result in the necessary set of functionality to do this efficiently that aren’t easily present outside of the BEAM.
With BEAM, robustness is a special feature. In the BEAM you can kill, restart and replace processes all over the place and everything stays working pretty well, because its structure means everything written for it is designed with that in mind.
In a typical async/await server side application sharing state across clients, killing, restarting and replacing usually means the whole single process containing all the async/await coroutines, and the fancy per-client state you were maintaining is lost.
You can of course serialise state, as well as coordinating it among multiple processes, but that takes more effort than just using async/await in a web app, and often people don't bother. Doing that right can get tricky and it requires more testing for something that doesn't happen often compared with normal requests. So instead, they let the occasional client session see a glitch or need reloading, and deem that no big deal.
At a high level, is the combination of process isolation, memory isolation, template delivery, websocket capability and resilience on top of all the standard web bits.
It will be really difficult to pull off with a good developer experience and minus several deficiencies outside of the BEAM. Anything’s possible though.
Typically you wouldn't use LV to handle:
Menu dropdowns, tooltips, popovers, modals (in some cases), tabs (when you don't want to load the content from the server) or things that change the client side state of something but don't adjust server state. That could be things like a "select all" checkbox toggle where that doesn't do anything on its own other than select or de-select client side check boxes or toggling the visibility of something. There's also things like wanting to copy to the clipboard or initiating stuff to happen on drag / drop (like animations).
Basically you'll still find yourself wanting to use JS with LV. Whether that's Stimulus, Alpine, Vue, jQuery, vanilla JS or something else that's up to you. But I do find most of the above necessary in a lot of web apps I develop.
> Typically you wouldn't use LV to handle:
> Menu drop dropdowns, tooltips, popovers, modals (in some cases), tabs (when you don't want to load the content from the server) or things that change the client side state of something but don't adjust server state.
My experience is that LiveView is fine for all but the last use case. And while in practice I often don't really need to keep things client-side-only, when I do it's often pretty easy to just write a bit of js and, if necessary, use hooks and events to communicate with the surrounding LiveView(s).
In fact, I vaguely recall that in the early days of LV, the creator himself argued that it should be used for just 'smaller interactive stuff'. Over time, we all discovered that LV does surprisingly well for SPA-type use cases (and as a result we now have stuff like router-level LiveViews (that take over the whole page), live_redirects, url updating, and so on).
> That could be things like a "select all" checkbox toggle where that doesn't do anything on its own other than select or de-select client side check boxes.
Why wouldn't you just keep that within the server-side state LV paradigm? I've done just that in a project I'm working on.
> There's also things like wanting to copy to the clipboard or initiating stuff to happen on drag / drop (like animations).
For those things you write js, yes.
> Basically you'll still find yourself wanting to use JS with LV. Whether that's Stimulus, Alpine, jQuery, vanilla JS or something else that's up to you. But I do find most of the above necessary in a lot of web apps I develop.
Absolutely, but I'm continuously surprised how little of it I need, and how often I /think/ I do just because I haven't quite wrapped my head around the different paradigm.
I wouldn't want to impose a 50-500ms+ delay on someone to show a menu drop down or a tooltip or most of the other things listed out.
With LV everything involves a server round trip. That's great for when you need to make a round trip no matter what (which is often the case, such as updating your database based on a user interaction), but it creates for very unnaturally sluggish feeling UIs when you use LV for things that you expect to be instant.
Even a 100ms delay on a menu feels off and with a good internet connection if you have a server in NY, you'll get 80-100ms ping times to the west coast of the US or the west coast of Europe.
LV feels amazing on localhost but the internet is global. I still think it's worth minimizing round trips to the server when you can, not because Phoenix and LV can't handle it but because I want my users to have a good experience using the sites I develop.
That said, if you want a different approach then check out my series at https://alchemist.camp/tagged/Reactor
I covered the whole process of building the site for my podcast https://reactor.am in the series.
Note that LiveView still isn't at v1.0 and breaking updates have been common. You'll have a much better with my LV tutorial or anyone else's if you use the exact same library versions we do and upgrade at the same point the tutorial does.
For things where you generally need a trip to the server anyway, like validations, it's great.
Maybe if you ran the server portion of PLV in the browser...but then you’re just back at React anyway I suppose.
Not many people know this, but a service worker (previously called "local server") allows you to run a little web server in the user's browser that intercepts requests to your own web site. (There's no open IP port.)
The service-worker web server can proxy requests to the remote server, and even build/store entire pages on the client side, enabling offline support. Service workers also have access to a local database, IndexedDB, running in the user's browser.
You can build a very fast web experience this way. You can easily cache individual pieces of a web page and glue them all together.
For example, you can easily implement server-side includes https://en.wikipedia.org/wiki/Server_Side_Includes or edge-side includes https://en.wikipedia.org/wiki/Edge_Side_Includes but running on a server that's running on the client.
Accidentally cache your index.js file? You are now stuck with your serviceworker forever (unless you do some chrome voodoo).
The promise is there, but it’s just a gigantic footgun.
Any issue with webworkers is almost by necessity opaque.
(IMO they should still be called local servers, or server workers perhaps. Service worker is too vague)
I'm doing a bit of a rewrite right now so this flexibility will come soon.
https://github.com/jon49/MealPlanner
Right now it only works offline.
I miss meteor. It was such a great framework and promise. Not for big sites really, but for mock-ups, internal sites ect. A while ago I started to look at it again. The drivers behind the project was essentially asking for input on what was preventing people from using the framework. The current state of the project is/was OK, except for the fact that it was hold down by all the guides and howtos referring to previous versions. It was not well documented what current best practices to follow, what to use as replacements for deprecated dependencies ect.
What the author is really getting at, I would guess, is that front end dev is awful, due to this weird combination of the Blub issue and a historical trajectory that has caused many problems.
The blub issues is mostly simple enough to pin down. Experienced programmers know that JS is an awful language. But there’s also a tooling or SDK “blub problem”. For example, compare npm and webpack vs gradle and javac (not to defend the Java ecosystem, but it does get some things right, or more right than others).
More idiosyncratically, there’s this historical arc of encountering fundamental problems, and trying to solve them within the current constraints of the web, rather than perhaps waiting for the web to standardise and evolve. This seems to be a mixture of lack of experience outside of this ecosystem (a bit like Blub) and, for this and other reasons, fixing problems “in your app” that should be fixed in the fundamental infrastructure of the web. It feels like technical solutions to social problems or, to use another metaphor, we are patching downstream what should be fixed upstream... if you build a house on sand, it will never be robust, no matter how many layers of infrastructure you add. That’s where the complexity arises.
It’s an enlightening exercise to step back and ask how you would build SPA infrastructure if starting anew. You certainly wouldn’t use a language like JS, you certainly would want to provide visual design tools as far as possible, APIs would be replaced with standard protocols, and probably you’d use a relatively small XML for layout. So perhaps only the HTML is anything like what you’d use. There’d be no transpilation, no webpack, no polyfills, no CSS, no JS.
In fact, what you’d end up with would look remarkably similar to the dev process for a Java applet!
I disagree with this. You might not want to use JS but a language “like” JS such as TS or Lua would definitely be on the table. Or just JS without the biggest warts.
> you certainly would want to provide visual design tools as far as possible,
I feel that the promise of visual design tools fell quite short. Issues with version control and general traceability of changes and the ultimate non feature parity with code make me think that code first interfaces are the future.
> APIs would be replaced with standard protocols,
Could you elaborate what do you mean? I assume REST apis but that is basically just HTTP.
> and probably you’d use a relatively small XML for layout.
As long as the language is robust enough to not move stuff around when the UI slightly changes. I feel that XML (and to an extent html) is too lax to express a programmatically created interface.
> So perhaps only the HTML is anything like what you’d use. There’d be no transpilation, no webpack, no polyfills, no CSS, no JS.
In a different world you could replace these steps by compilation, compiler, backwards compatibility libraries, a styling framework and a language of choice.
I think you have shown that JS ecosystem has grown very organically. I think this is because the nature of web developers was to put stuff out rather than really think about how do make it the correct way. I believe this is because of constraints, on a native platform you had the option to go down to assembly or create a new language or paradigm. On web only the browser vendor has this power, all the dev had was JavaScript.
When you remove the warts from JS there's not much left. And I'd be pretty skeptical of someone starting a new project in Lua today. I think the mainstream choice for a "blank slate" language today would look something like Swift or Kotlin; Typescript can gets close, but it still has a lot of JavaScript baggage you'd want to strip out.
> I feel that the promise of visual design tools fell quite short. Issues with version control and general traceability of changes and the ultimate non feature parity with code make me think that code first interfaces are the future.
All the big UI libraries end up offering some kind of markup/constraint-based interface - which is ultimately data rather than code. And for editing that, a visual form designer makes a lot of sense. I like Qt's approach - you visually edit a markup form that's compiled into a class you can subclass, so you don't have to deal with the problems of code generation, and the markup is relatively version-control-friendly.
> Could you elaborate what do you mean? I assume REST apis but that is basically just HTTP.
I'm not the person you replied to, but thrift/gRPC are a lot nicer to work with than REST APIs. Standardised protocol definitions that let you understand what kind of changes are or aren't forward/backward compatible, and no need to write a bunch of boilerplate by hand.
> I think you have shown that JS ecosystem has grown very organically. I think this is because the nature of web developers was to put stuff out rather than really think about how do make it the correct way. I believe this is because of constraints, on a native platform you had the option to go down to assembly or create a new language or paradigm. On web only the browser vendor has this power, all the dev had was JavaScript.
It's the same story as "no-code" tools: IT departments won't let anyone install an application runtime, but they're happy to install a "document browser" and let it run arbitrary code. It's understandable, but depressing.
Modern JavaScript is pretty sweet to write compared to pre 2015. It sure is fun to join in on the "JavaScript bad" circle jerk though.
Yeah, it's increasingly clear to me that Java was just 20 years ahead of its time. Java really would make a great front end language.
People lament the complexity and size of the JVM... But these days V8 is just as bad. The complexity is a trade-off for runtime performance.
It's compiled into a compact easy to parse bitcode format similar to WASM. It's faster than JS and shares many basic design decisions. The packaging system is and always was basically a better version of NPM. It has pretty good cross-platform UI, probably the best there is outside of QT.
WASM apps are eventually going to be built identically to Java cross-platform desktop apps. Probably using Java, Go, C#
I hope not. The world is finally waking up to the need for sum types. A big part of the reason Java is so hated for doing simple things in is that lacking sum types meant it had to implement a horrible "checked exception" system.
Hoo boy it was awesome to work with. But. It came out at the wrong time. Linux was coming up as a desktop, MS was still evil. Mono was mostly a hobby project.
The backlash of trying to use "proprietary M$ crap" for web was too big of a hurdle to cross, even if the technology behind Silverlight was lightyears ahead of the drek that was Java Applets.
If the JVM had access to the DOM, you could write SPAs in Java and everybody would be happy. Instead Java sealed itself off separately from the browser, and Javascript went from little toys to full-blown UI applications. And then developers wanted to use the same code on both client and server so they made Node, working in the space where Java is so much clearly better.
So we end up with the worse language running the world. Fortunately, JS has finally become a mediocre language (or even a decent one with TS), and here we are.
BS blanket statement.
Some - many, maybe - programmers that in all likelihood multiply your experience and talent by orders of magnitude believe it's a great language.
Not everyone working with JS is doing so with a gun to their heads.
TypesScript, maybe.
Out of curiosity, as a Java enthusiast, I was wondering if you could give examples of what you feel is wrong?
In my HN browsing I find Java is rarely actually discussed here, though often dismissed. I don't know why.
However the culture around complex frameworks and over-engineering is what most people really dislike about it.
IMO pretty much all the advantages touted by Java proponents (such as: good language design, easy of use by heterogenous teams, speed, etc) are correct, but are negated by a large part of the culture and ecosystem. The memes about humongous class names and 200-method stack traces are true when you use the popular frameworks and techniques.
Of course there are exceptions to this and this can creep into other languages too, of course.
I think there's a lot of criticism for Java's language design. It involves an awful lot of boiler plate, and is generally very verbose. It's also a language that forces you to use OO, and OO has received a lot of pushback over recent years - so that approach has become very unpopular.
Personally, I also think the use of so many design patterns is an attempt to compensate for what the language lacks, its reflection capabilities are flawed etc.
I don't hate on Java. For many years it was my main language. It has awesome tooling and the JVM is incredible. But I do agree with most of the criticism.
I've been learning Clojure recently and Rich Hickey's talks often begin with some motivation including criticism of Java and OO more generally, here's one such video: https://www.youtube.com/watch?v=VSdnJDO-xdg
Personally, I feel like Java is not really as hated as some people make it out to be. It's a stable language that very few people choose for their "cool side project". At the same time, it has excellent tooling, mature and prod-ready open source frameworks, and backing of some giant companies.
This is not to say that Java is perfect. I think most dissatisfaction comes from students or junior people who are baffled by the complexity of Maven/Gradle configurations, strict project structure (where a class can be 10 directories deep), and Java's insistence on boilerplate (which is often challenged by new Java releases. Those, however, are quite rare in production; I'm starting to see Java 11 here and there but the majority of projects I've seen run 1.8).
The basic idea being that you know a tool that's obviously superior to a lot of alternatives, but you're blind to how different alternatives are superior to it because you can't grok the power beyond their initial "weirdness".
http://www.paulgraham.com/avg.html
My understanding is that everyone understands the features and ecosystem benefits of languages they work with, but not necessarily understands those of other languages. As a result, the value of their opinions on other languages may be mixed.
Typical hipster web dev now days! Go back to the basic.
You can choose Wasm for LOB apps or on fast connections.
You can choose Server hosting for apps that have about 100,000 users at a time. Mind you, that is 100,000 users concurrently. Which should be more than enough for most apps.
There are plans to reduce bundle size and server side resources, coming in .NET 5.
As per Microsoft Benchmarks[1], it should cost about 100 USD per month (3 years, reserved instances, paid upfront) to handle 20,000 concurrent users. (This price is not including database, storage, etc). That comes to about 0.18 USD per user, for 3 years. (cost of serving app to 1 user for 3 years in total). Which seems pretty reasonable, especially if you have a decent, paid app. The cost comes down even more, if only a %age of your users are online concurrently.
On Digital Ocean, a similar machine, would cost about 40 USD a month. For 3 years, total cost for 1 users will be 0.072 USD
[1] - https://devblogs.microsoft.com/aspnet/blazor-server-in-net-c...
At the same time, while not condoning it, I just scrolled to the bottom of Amazon's front page and downloaded over 30 MB.
I have to wonder if you actually use ASP.NET Core yourself, because ASP.NET Core 3 is, IMO, fantastic. ASP.NET used to be a bit clunky, and lacking in extensibility points, and a lot of people used alternatives like Nancy instead. Nancy officially stopped development around a year back, largely because dotnet devs just don't need it anymore. I was a long-time Nancy fan myself, ASP.NET Core 3 has all the best bits and more.
And you don't need to stick with the typical paradigm on controllers in one folder, views in another etc - feature folders work great. Hell, you don't even really need to use controllers, if Razor Pages are your thing.
Right now, we use Blazor with server-side rendering for our internal dashboards. This feels almost perfect to me. There are still some rough edges and I still have to ultimately deal in terms of HTML/JS/CSS.
I've got a side project that takes the Blazor server-side concept to the absolute extreme. But, I haven't had much time to work on it this year considering... Hoping to get back into the crusade in early 2021. Looking to pilot it as a replacement for one of our Blazor server-side apps in 2H 2021. One of the bigger objectives is to develop a web application that is perfectly auditable and secure as possible. If you render final client views on the server, you can DVR precisely what each client is experiencing. The client source can be ridiculously lightweight and betrays nothing regarding the business. My prototype currently serves a ~50kb single-file HTML payload that runs the entire show for each client. I am looking at things as deep as server-side rendering of the mouse cursor. Looking at each client as a simple event stream from the server's perspective is a really neat way to organize this problem.
I can now create entire working apps using just Elixir code and the utility-style Tailwind classes within my server-side templates. I still need to write some js and css, but where LiveView reduced the need for custom js to a minimum, Tailwind did the same for css.
This. This is the sentence I am going to use to describe Blazor Server from now on.
- Rails
- StimilusReflex
- view_component (https://github.com/github/view_component)
- Web components
With these 4, it divides responsibilities very cleanly/pragmatically: Rails is your app framework. view_component is how you divide your view into an organized/flexible structure. StimilusReflex is the "reflexive" bridge between the 2.
What happens when you need just a sprinkle of javascript to re-render a component when websockets/StimilusReflex are too slow (ie: user interacting with a color picker or something)? You could use Stimilus.js to sprinkle this interactivity... BUT you might end up with duplication between your view_components and your Stimilus.js controller. If you use webcomponents, then you can follow the open/closed rule: Your view_component can only interact with your custom webcomponent and then your webcomponent knows how to render/re-render those custom bits. So it doesn't matter if that webcomponent is rendered from: initial page load, StimilusReflex, or rapid js events (before they are throttled to StimilusReflex), it's all goes through the webcomponent "front door".
It's so great to still be super productive and be able to crank out several pages of an app in a few hours vs most of the React / SPA codebases where you might send the whole day on one little component.
I come from the "js sprinkles" approach that rails has always favored, and this feels like a logical next iteration. I sometimes wonder why Basecamp doesn't publicize Stimulus a bit more; I really only learned about it at rails conf. It feels almost like it could be a part of rails itself, and it's the kind of thing that is useful for almost any full stack rails app that does server side rendering.
BUT basecamp libraries (turbolinks, stimulus) are horrible open source libraries. There are not any changes or bug fixes for months now (for both) and nobody does know whats the actual state, whether they are abandoned or basecamp is working on something new. Then hey.com released and people found new features in both frameworks, so one day they will release (again) completely reworked versions of these libraries they have been working on in their private repositories.
Both libraries are really good together, but they would be better if developed more open by the community. They are basically abandonware the day they are released, until one day a complete rewrite and major version bump is released.
OTOH all these component based frameworks have definitely brought us a much better way to produce interactive experiences compared to the jQuery days. This is not related to SPAs at all. You can use React/Vue/etc in a multipage application. The problem is that to hydrate (make interactive) the server rendered HTML you now need to duplicate your markup between your server language and front end framework. The solution is to use the same framework in the backend and the front and write the components just once.
The stupidity and hostile fear of originality I detect in this these comments is a very real reflection of my professional experience. This, dependence on frameworks and inability to imagine anything beyond the common SPA, really scares the shit out of me knowing I will be coming home from a military deployment soon and returning to the corporate world are scared to write code.
Whenever non programmers ask me what programming is like I tell them it’s full of the most insecure people you can ever meet. People are afraid to do their jobs, need a framework for everything, and always talk about how hard it is (when it isn’t).
That is a pretty bold statement to make.
It does take skill to make a proper SPA not to make an SPA.
While it's not bad, SPA forced you to do view validation twice, one on backend and another on frontend. (Generally)
Let's say that in HN not everyone can view upvote score of comment. With classic server rendering, you can put the check on view directly (though not recommended, it's sometimes useful to cut corners) and it's guaranteed that those users won't see the score.
OTOH you can't do that with SPA, since you can easily sniff the content via API response.
Of course, the hypertext we have, HTML, wasn't completed, and it leaves a lot to be desired. I have tried to fix that with htmx:
One quick question: How should I be handling server side errors with this? Like, normally I’d check the status code coming from the server and throw up an error modal if it’s an error - what’s the equivalent mechanism here?
For server errors you'd use htmx:responseError:
https://htmx.org/events/#htmx:responseError
You could write some code like so:
htmx.on("htmx:responseError", function(evt) {
GrowlNotification.notify({
title: 'Request Error',
description: evt.detail.xhr.responseText
})
})
And that would show a growl notification in the event of an request error. Or however you wanted to display it.I wouldn't consider it particularly elegant, but it's straightforward and has worked well. It uses the "complete.ic" event to trigger whenever an intercooler request finishes, and then uses the response status/code/text to display an appropriate message.
LiteDOM https://litedom.js.org/
Stimulus https://stimulusjs.org/
Turbolinks https://github.com/turbolinks/turbolinks
Laravel Livewire https://laravel-livewire.com/
Phoenix LiveView https://github.com/phoenixframework/phoenix_live_view
That's where I see a lot of potential. With Stimulus Reflex I have the convenience and development speed of Rails and I can enhance it with StimulusJS sprinkles and reflexes to create great experiences for the user. The interactivity I get is enough for 90%+ of the webapps out there and the complexity to do it is far less.
I've settled on Alpine instead for the time being because it has some data management built in. I'm thinking I'm going to have to switch to Vue on my current project because I feel so much less productive with Alpine.
I now dread the time I have to write those infinite lines of JS, conflicting dependencies, slow build times, React hook state management etc.
When I speak with my colleagues about tech, they all seem to love the entangled mess of JS dev and willing to jump on any new framework that gets released. I always push for good old reliable SSR. Often get called the weird one for being young, yet favoring old school tech, though.
I guess I prefer a better developer experience and shorter time to production/market, rather than spending days trying to setup a project and figure out weird quirks and issues with such a complicated mess of a "serverless, modern day web application".
When saying that Laravel/RoR gives you all that by running one simple command, I get blank stares. Hard to believe, I know.
-Do you want functions?
Use our proprietary platform
-Do you want to store content?
Use cloudinary, aws
- Authentication?
Auth0,firebase
- Database?
Use FaunaDb and our super cool new query language that nobody knows and cares about.
> Congratulations. You've built your new webapp on Jamstack. Now you have to manage large bills across hundreds of 3rd party services, vendor lock-ins. Also good luck trying to reproduce all that on a development machine or organize your code.
On the other hand you can just: laravel new project-name --jet and deploy on a single linux machine or heroku and you get:
-Robust and customizable Auth, password reset, 2fa
-A serious db like PostgreSQL and an orm
-SSR by default with 0kb bundle size!
-Any css tool you need
-Easy APIs, tokens and permissions
-Truly open source.You have full control of your code and data
So yeah it's just a command but yikes, who uses PHP in 2020, right?
> HP roles typically pay 20% less
Yeah, true. Hence why I am a React dev professionally
But at some point, it's neither a hacky Lisp like language, nor is it stable like Java or C++. It's just a middle ground that does these things poorly.
It would be nice to have a new programming language from scratch built to handle all the async/reactive mess. But until then JS is our best bet.
```
try {
return await fetch(url);
} catch (e) { handleError(e)
}```
Because that (metaphorically speaking) is 90% of what I write. Throw in the occasional closure, `map()` or `reduce()`
My day to day headaches are never from TS, and always from unpredictable DOM api/layout/style behavior.
I guess I just don’t have any frame of reference for how “nice” a language can be. Is it just that JS has so many “bad parts” and footguns that I’ve gotten good at ignoring?
Vue and Svelte, IIRC, were authored by designers. Not C or Java programmers. Perhaps React has a different history.
Pretty sure they were just sharing thoughts.
But honestly, this is because mature backend frameworks can be REALLY nice.
The framework that I feel makes development less ugly is svelte. But still, I really don't like the idea of heavy client side websites. It really makes everything more complicated and the user's device slower.
I love the simplicity of Turbolinks, I love how clean svelte code is and I am trying to figure out the "glue"
• Write the glue code yourself if you only need svelte on a few pages • Inertiajs if you want to replace your view layer with svelte
Right now the "glue" I came up with is a silly connection between the server side router and the "Entry" component of Svelte. It works, it's 10 lines of code, it's clean and the website is super fast. But, both Inertia and my solution feel somehow "hackish". Not a proper pattern.
But really, anything to avoid client side routing, state management and auto-magic code splitting.
I'm convinced that this is the solution for the majority of use-cases, combined with selective usage of either React components or something like Stimulus where you need more sophisticated UI components.
If a client tells me what they want built, I bet I'd be able to roughly guess how much js there's going to be, probably within a few hundred lines for a, say, 3 month project.
The larger the project, the large the margin of error, but still, it's really not that hard for the vast majority of work we do. Or at least I do, e-commerce, enterprise apps, etc.
Almost never had a problem with HN either
And yet, it still uses 130 flipping megabytes of RAM, more than Youtube does, as well as more CPU than Youtube does at idle, as well as requiring several seconds to "start up" when first opening a tab. Ridiculous.
If a non-SPA page loads near instantaneously because the client-side rendering isn't bloated, it can feel just as good as an SPA with spinners.
You can also use tools like turbolinks the author recommended, to turn your non-SPA into an SPA.
SPAs can start off with the good intention of being low-latency and responsive. But when you're backed by a web server, you still have to account for it though optimistic rendering, prefetching, and loading states. Getting it right can be an excellent UX, but it's easy to get very wrong.
I wonder how many of the people crapping on SPAs are actual front-end or full-stack app devs, or otherwise people developing very close to the UX.
I'm sure there are some disgruntled UX devs who are running back to SSR, but when I come to the bimonthly "SPA sucks" thread on HN, for the most part it feels to me as though the critiques are coming from people for whom UX and front-end development are secondary concerns.
This is an interesting perspective. To me, SPAs blur the line between what's happening locally and server-side, so my impatience with slow functions on an SPA page is much greater than the same thing happening on a SSR page. Maybe it's just my conditioning to expect things on a single page to work much quicker as opposed to moving between pages.
IMO, well-designed SPAs should make use of the context-switching function of a complete page fetch in situations where the user might need to wait a relatively longer time for something to load instead of loading bars/spinners.
But totally agree with your position on this in general!
Yes, but you often pay a huge penalty on the first page load, which for many use cases is the most important. I'd be so happy with a turbolinks version of GMail.
It's incredibly wasteful to do a SPA for one autocomplete field, or one map widget, etc. HTML delivered directly to the browser is very responsive.
Depends.
Pressing a key and not seeing a character in less than 50-100ms, yeah, it's quite frustrating.
Clicking on a link and waiting for the content to load? Not so much.
For most apps in Phoenix LiveView, it's probably best to think of this as a "relatively smart caching layer". Keeping state on the client invokes distributed state concens anyways, and in the case of the Phoenix, at least the VM is well-equipped with the relevant primitives to make distributed state easy, especially. Basically the only cost you have to pay is if latency is a big deal, you are making a trip back and forth to the server, which could be 100s of milliseconds or more in bad situations... Or even really bad situations, like driving under a tunnel, or being in some stretches of subway.
Reminds me of Wicket's AJAX support, which is still the best web development experience I've ever had. You keep the state in the server-side session, when the user pushes a button you update that state and re-render those parts of the DOM that changed because of it. It dovetails nicely with the whole framework being properly component-oriented - rather than the page-oriented MVC style, you make encapsulated, reusable widgets that know what their own state is and how to render themselves based on it, and the actual top-level page becomes almost an afterthought.
[1] https://99percentinvisible.org/episode/the-next-billion-user...
That said, something that requires a lot of thought is not just constantly displaying spinners. When I look at projects built by experienced FEs it seems like there's a lot of patterns to work around this that I'm not aware of.
I'm not sure what patterns you're thinking of. To me this just sounds like implementing caching and background fetching.
The problem with frameworks like Django is that they have no real concept of UI Components. They have glorified ways of copy pasting html code. The cognitive burden when creating a fairly complex app, like a set of dashboards, is very high in Django.
The reason people flock to React is because, once they develop a component, it's easy to re-use. And that is the drug that fuels them. However, the learning curve is high.
I found Blazor to be a good middle ground, because it has the concept of Pages (Razor pages), which are linked to URLs' and those pages can contain re-usable components. The framework is setup for basic site structures with a lot of options for customization. For example, you have default layout pages, that are included in every output. Great to put a basic menu and footer system.
Those working on ASP.NET MVC and like would find it a breeze to work on Blazor.
Couple that with the option of using C# for the whole application, it is very enjoyable to develop with.
I have used Angular, React and Django. Angular, for me, is too much complication for simple stuff, but perhaps works well with complex apps. However learning TS, as good as it is, was a turn-off for me. React is easy to start with, but as your app grows in complexity, it becomes hard to manage and think about various stuff like state management, routing, etc. Given choice between React and Angular, I would definitely choose React. Django is very good for sites like blogs or info pages, basically wherever there is a large amount of static content, pulled from database. Of all the above, I found Blazor to be very productive. I can also mix and match different paradigms and Dependency Injection is a god send.
Especially since it works with every tech stack with pretty much no code changes required to your existing app. The next iteration of Turbolinks will also work for form submissions without any server side code according to what's been publicly discussed from Basecamp employees. That and partial page changes will be possible with Turblinks frames which is a huge upgrade.
A while back I made a video on the benefits of using Turbolinks and how to set it up if anyone is interested https://nickjanetakis.com/blog/improving-your-page-load-spee....
Just be mindful that Turbolinks alone isn't enough to replace a SPA. It's typically paired with Stimulus but you can pair it up with jQuery, Alpine or whatever you want when you want to do more than page transitions, form submissions and swapping content in a specific area of a page.
In majority of cases, especially when building tools like back offices it's not what you want, you just want to be able to render forms, tables and save them in a convenient way.
I've found turbolinks + simulus.js combo to work surprisingly well. Actually, I use the only one stimulus.js controller in majority of cases - one that makes an ajax request and reloads the page (with the help of turbolinks) on success. If page load time is fast enough, the use experience is the same as if you would change the dom with js manually. Of course the requirement is that reloaded page reflects the changes.
Other stimulus.js controllers are there for the cases that don't fit into aforementioned pattern. That sounds primitive but can take you a really long way without turning your js into a a monster.
In addition to that you don't need to care about the routing, html validation just works, you can wrap existing html components and even inject react apps here and there if you really need to.
[EDIT] Forgot to say - this approach does not force any language or architecture on the server-side
It can do client side rendering, server side rendering, and static site genration.
From a previous this week in matrix(2): "Hydrogen tries to be the lightest Element. It is written entirely in vanilla javascript (no React, no Webpack) for complete control, structured as an MVVM app, leveraging the raw performance of indexeddb."
(1) https://github.com/vector-im/hydrogen-web (2)https://matrix.org/blog/2020/08/14/this-week-in-matrix-2020-...
The SPA pattern is fine, it is React Router and Redux that has overcomplicated things.
Here's an example of an app written using the MVC pattern that is way simpler than the React stack: https://github.com/Rajeev-K/eureka
It uses two very simple libs:
A 500-line router: https://github.com/Rajeev-K/mvc-router/
A 200-line templating library that uses JSX syntax: https://github.com/wisercoder/uibuilder/
Next.js gives you a great toolbag to choose from for each challenge, it's definitely going to stay around and keep growing like crazy.
JAM has other problems. I don't think that's one.
Breakout indie success stories are often lead by artistic types, since it seems harder to teach a typical programmer to draw than to teach an artist enough code to get by. And I think the scene is richer for it.
Is there a good reason the web isn't like this? Engines, rather than frameworks, that have done the hard optimisations and made the best practice decisions for us?
A website, often these days, is an ever evolving beast forever changing and adding features to it is (apparently) imperative to ensure that the gravy train keeps flowing. Its one of the reasons why I think there's an increased focus on developer productivity in web frameworks, libraries, and tooling rather than a focus on delivering a better solution.
Turbolinks you can have with an SPA codebase that will just request/load on clicks, and post/load on forms, not a big deal either.
https://medium.com/@obie/react-is-dead-long-live-reactive-ra...
Too much JS being executed on every page.
Using this stack I'm able to build a highly reactive apps with minimal efforts.
https://qbix.com/blog/2020/01/02/the-case-for-building-clien...
E: Actually it might just be a really heavy page. It’s a disaster on mobile.
E2: After a few refreshes, it seems to be loading normally.
It's still opinionated, but only on the data loading part! It's just a small library that will slot into any stack. I'm the author.
https://medium.com/@mlrawlings/maybe-you-dont-need-that-spa-...
I've recently started a new project with preact and an express backend, and I'm in love with the smoothness of the dev experience. Seems like all my problems have been encountered already, there's dependencies and heuristics for everything. I'm just really productive and my app looks great.
Surely, all of that wouldn't be the case, had I tried some random new technology...
Native applications
nothing to do with the SPA of course
Was your comment just an attempt at some growth hacking?
- No JS fallback by default
- Naturally friendly to XML database backends
- Huge cache hit improvements
- Effectively, you get the functionality of the now abandoned "seamless" iframe attribute
(Jokes aside, I tried this years ago hoping for it to be a magic bullet. Gzipping meant that the bandwidth savings weren’t anywhere near what I hoped and XSLT is a PITA to deal with)
https://github.com/turbolinks/turbolinks#working-with-script...
It surprises me that there are so few implementations using this pattern today.
The Meteor pattern is another good one for the user, if you like things better optimised for user-visible latency (as user interactions happen at the client first), but it hasn't ended up with much mindshare now. Perhaps because it's more complicated to use, and perhaps because JavaScript isn't ideal for this.
Svelte's precompiled diffs and minimal client-side code is another pattern I like.
For an application I worked on, I developed a combination of those three patterns. It had a nice and very efficient combination of server-side rendering and client-side immediate interaction, without needing custom JavaScript. This made it fast, user-friendly and pleasant to develop in.
Like LiveView, the client would send user events to the server, which would update affected component model state (which could be shared among different clients too). Server would re-render any visual components which used the model data (using automatic dependency tracking from previous renders), and then send an async event to each affected client containing an efficient diff of all rendered changes. If there was much network latency or too much queued, multiple updates would be batched together, merging their diffs efficiently. The result was the update could be worst-case the size of a page replacement for any number of updates, and at best the size of a few DOM edits in place.
But, a little bit like Meteor (but without custom JS), the server could also push "client event-handling hints" in the rendered model to the client. If an event pattern-matched one of these hints, the update could be applied immediately on the client as well as the event sent to the server. The server knew what update would have been applied, and could account for it in the diff. So if the server's new rendering matched the client's immediate rendering, the diff was empty and didn't need to be sent! But if the server got a different result, for example the event caused an operation which failed, the diff caused the client to receive an appropriate correction.
The diffs were calculated efficiently too, not by rendering components and comparing trees, but by precalculating diff trails from state change patterns where those could be recognised. For example when one model value changed, if the diff would always be just a string change in the DOM, it already knew and emitted that diff directly. This meant diff calculation time was as fast as possible in simple cases (event to output in O(1)), and reduced to a reasonable diff time in the most complex cases (such as merged diffs).
Keeping it always perfectly in sync and always efficient, throughout network outages, reordered requests, lost events etc was quite technical, but it wasn't application specific. Only the framework needed to deal with the technicality.
This was lovely, because it always stayed in sync, it was always efficient for any combination of initial loads, reloads, and sync events, both on slow and fast networks, it worked without JavaScript if needed, had client-side immediate updates for simple logic of a general-purpose nature specified by the server-side, could share model state among different clients and pages, and still didn't need any custom JavaScript for the application.
As the server side was written in async coroutines and Perl, it didn't seem worth the effort of packaging and publishing that implementation as Perl's popularity declined (and indeed coroutines seem disfavoured there as well, even though they work brilliantly).
I still think that's a lovely interactive webpage model, possibly the best. Nicer than client-side SPAs and nicer than server-side rendering. It's pleasant to develop for, pleasant as a user as well, very fast in many different scenarios including poor network connectivity, and great for sharing live state that appears in multiple pages or documents.
I'd like to implement that again in a modern language, but I haven't had any compelling reason to work on a webapp lately.
Perl now has http://p3rl.org/Future::AsyncAwait which is (like any async/await system) a bit more restricted than a full coroutine but works beautifully.
If you threw a github repo up somewhere I can think of a few people who might be interested in trying to update it to more recent+reliable perl tech.
as one dev working part time, i am still able to build for netscape 3 and lynx, adding from there.
Granted, I am allergic to developing any JavaScript myself because of how many anti JavaScript comments I have read on hacker news ;)