My company (4,500+ people) ordered all products in their portfolio (~12 web apps) to migrate to SPA front ends about a year ago as a way to stand out from our competitors, and boy has it been painful.
Prior to that initiative, we had been using the hybrid approach mentioned in this piece, embedding SPAs only where necessary and sticking to SSR everywhere else, which worked really well.
Since the announcement, our productivity has diminished dramatically since so much of our time is now focused on re-working functionality that already exists into an SPA, and it's completely unnecessary. Not only that, but extending these UIs will take more time in the future than their SSR versions due to the added complexity of the front end frameworks, and we're definitely going to make mistakes along the way that we weren't making before.
It drives me crazy to think that some exec came up with SPA-ing everything as a sales pitch to clients, when 99.9% of our clients have no idea what an SPA is. And the amount of money being spent on turning already-working apps into SPAs is astronomical.
I've been working alone for so long I've not had to deal with anything like that for years, but I'll offer this...
Doesn't matter, so don't let it matter to you.
When I worked for others I'd offer my opinion and advice and when it was ignored I'd do it their way every step of the way because it really does not matter. You get paid the same either way.
I'll add that because it didn't matter to me I ended up getting to work on some pretty cool stuff. Everyone knew I wouldn't whine about changing directions or being taken off a project and jumping on whatever they wanted so I was almost always the 1st choice to work on something new.
When that happened I was often able to influence the direction of the work.
All you can do as a professional, with experience, is offer up an argument and attempt to make it convincing enough to compel people to do things your way. If they reject your option, defend only once, and no more. After that, simply step back and work with whatever technologies are decided upon.
You can also attempt to work the social networking game and play (internal) politics. If you do these successfully you're more likely to get your ideas heard and implemented. I find this tiresome.
Ultimately if I'm being polite, professional and basing my arguments on facts and evidence, and they're being rejected, I'm not expelling any more energy on this front. Move on. Work on and with what's decided and have fun doing it.
This doesn't seem like a problem of "MVC vs SPA".
The same problem would occur if you were ordered to rebuild 12 apps written in Rails ( or whatever full-stack MVC framework) in a different one, like Django, for example. You'd experience the same pain.
The story of rewriting Netscape comes to mind and a few others. Point being, not much value in rewriting something that works in different language.
> Not only that, but extending these UIs will take more time in the future than their SSR versions due to the added complexity of the front end frameworks
Compared to client side rendering discrete web requests with minimal templates; you usually get much better separation of logic, view, and code than the typical serverside solution.
There is a happy medium where server side services are encapsulated to separate concerns in a similar manner, but it rarely happens, even with competent, experienced, well intentioned teams.
I’ve been doing this for 15 years, and if I’ve learned anything it’s that developers can figure out ways to abuse anything.
If you can't separate concerns in a hybrid MVC pattern, you'll be screwing it up just as much in an SPA.
Plus you've got the extra layer of an API to maintain too making it even more complicated, and more likely to spaghettifi, not less.
Its always possible to architect the web/app back end to do everything through APIs, keeping the APIs pure, and ensuring that others will be able to build UIs on top of them.
But in many organizations the same people that own the APIs also own the back end. That means it takes discipline and an acceptance of extra costs to keep this separation. Its easiest and cheapest to just slop all the back end together.
With an SPA, a different team builds the front end from the back end, and APIs are the only way for them to talk. That acts as a force for good APIs.
Fortunately, I inherited a set of pretty well-maintained SSR rails apps, and they've been pretty straightforward to continue working on (with a couple of exceptions).
The single biggest disadvantage I see with front end apps is that comprehending state management via redux and co. is so complicated, and so, so easy to get wrong.
I can tell a coworker to refactor a smelly ERB view and extract out a new template, presenter, whatever. But redux still causes us problems that require refactors months later. It still feels way more cumbersome than being diligent about keeping controller/presenter/template logic clean. We're also far more competent rails developers than we are modern UI developers, and that definitely factors into our productivity.
If you don't have good, experienced senior developers or they don't have discipline, yes. But that's true for any technology. Good developers have the knowledge for simple things like how to separate business logic from templates...
But I've seen the same thing happen in the SPA. Where one person calculates some value in an API method, another doesn't know about it and calculates it again slightly differently in a different method leading to app inconsistencies. And SPA's make it worse not better because it sometimes forces you to write a piece of domain logic twice, once for the browser and once serverside.
I honestly don't know what's wrong with accessing query strings or session information. But I think maybe the reason you've seen template code using global state is because the template code was just written earlier back before that information had really soaked into the entire development community.
The key being bad programmers dont isolate concerns and good ones do.
MVC approach was a hairball of code where 2/3 was dealing with synchronization of state between client and server, and only 1/3 being related to actual application logic.
Clean separation of frontend SPA and backend API made both sides simpler and more robust.
I would also wholeheartedly recommend separating the development into two teams (frontend / backend) . It makes both pieces of the application even more robust due to both teams guarding the interface with the other part even better.
In theory, we should strive for that. In practice, back-end team tend to strive on "technical purity" and would ask the front-end team to take any hacks/workarounds necessary to deliver "compelling" user-experience. One example would be the disagreement over "Data Model" of front-end vs back-end.
It sound as though the application was a suitable candidate for an SPA and should have been developed as one to begin with?
We have a flagship product written in web forms (started in 2006). It's a big solution. Performance has always been a challenge with it.
While I'm not proposing a complete rewrite into SPA, due to - migration requires a lot of effort, huge risk for missing functionality, errors etc.
The biggest problem with the product is - app posts back the entire page, which most of the times is huge, even if we changed just one field. The viewstate is enormous. My proposal is to switch to json objects for information exchange between server and client. We'll get the benefits similar to SPA without rewriting for it.
This approach is also described in MS's silk project - https://www.microsoft.com/en-us/download/details.aspx?id=272...
If I understand your approach correctly, I often do something similar, but with modern ASP.NET Core MVC apps. Basically, I have a tiny bit of JavaScript that 'intercepts' all form POSTs and submits them using AJAX instead. Another tiny bit of JavaScript can then process the result and do something (update a table, display a message, redirect, whatever).
I feel like this gives me the best of both worlds - the backend is very testable, and really straightforward for new developers to come up to speed on, while at the same time we remove a lot of full-page renders.
You can find an example of this technique here[0]
For instance, if you start to rely heavily on dynamic capabilities to render key components, such as detail views/overlays, then you have to start reasoning about making them accessible via their own URL to enable direct access, browser reloads, sharing, etc. By the time you've done that, you've started duplicating browser functionality via routing, history, etc, and generally working to create an app that coexists peacefully within an app. In other words, you quickly move into SPA territory and all that that entails.
But, if that causes you to be more conservative about sprinkling in dynamic capabilities, then you're really much closer to an old school SSR app and not realizing a lot of the purorted benefits of a SPA, or much else beyond the old school AJAX approaches. Not to say that's useless, but we've long since been down that road, and it doesn't represent any new thinking.
So, it's just hard to find balance there. In most cases, you're really either a SPA or you're not.
I think the real issue you are dealing with is what others mentioned: rebuilding something from scratch burns a ton of people-hours and money. Asking a bunch of rails developers to lean into FE development is a recipe for animosity and to me it shows in this post.
Remember, every time you tell your boss to do something they don't want to do, you're telling them to spend money they don't want to spend, and if it's something you were hired to do, you're also placing your own value as an employee in question.
But more importantly, I also find server view rendering to be a faster, better UI experience. It's really frustrating having to wait several seconds for a SPA to load, or to have unexpected behavior when clicking the browser back button, or failing completely because some random hunk of JS garbage errored out, and it's one of the big contributors to why I don't really like using Facebook or Twitter anymore. They murder my browser with megabytes worth of slow SPA crap to give me less than a few kilobytes of meaningful data (and/or people screaming at each other). Gmail now takes 10-20 seconds for me to load at this point, on my high end laptop. I just want to switch to HTML mode by default.
I definitely get edge cases like Slack, but honestly don't think SPA has been a positive development, overall. I think the web was better as a document/HTML oriented design.
It's super fast. Almost absurdly so, compared to the "full" gmail experience. Added bonus: It gets out of the damn way so you can just do what you came there to do: write and read email.
It's certainly possible to have a server rendered app that uses JS sparingly for interactive behavior, but it blows away a lot of the benefits once you're doing significant DOM-manipulation.
I did this a while back, and the only real issue I've had with it is that there doesn't seem to be an equivalent to the "Check mail now" action for imported email accounts. (The 'refresh' link annoyingly does not trigger this action.)
It was nice and would still be nice if browser caching meant a site still worked well over a bad connection. But you can be browsing around a "static" site and hit the back button and be stuck staring at an empty or partly rendered page waiting for your flaky connection to load the page.
SPAs handle that situation better even for sites that are theoretically not suited for SPAs. The simple principle of doing your best to display the data you've already fetched is extremely refreshing compared to supposedly "document-oriented" sites, which typically take the opposite approach -- we showed you this page fifteen seconds ago, but we can't show it to you again until we exchange a few megabytes of data with headquarters. And now we can't show you the other page, either. Just be patient. If it's really that important you should have taken a screenshot, mmmkay?
(Slow-loading web sites are the main reason my not-so-tech-savvy family members, who are very stubborn and selective about learning anything, are all adept at taking screenshots on their phones. When it comes to information they might need later, they take screenshots, because you can't just leave a page open and trust it to be there when you need it. You might accidentally trigger some navigation and then who knows how long it will take to get back to the information they need, if it's even possible.)
Browser caching should theoretically let a document-oriented web site work smoothly over a flaky connection, as long as you stick to the pages you've already viewed, right? But how often does it help even a little bit? Maybe SPAs will eventually be just as broken, but right now it seems damned cool that they make a good-faith effort to show me stuff.
But even Slack is subject to the same clunky and slow user experience you're describing because its entire user interface is an SPA.
In my opinion, a site for the SPA hall of shame is the Starbucks.com progressive web app [1]. My grievances about it are legion, but to name a few:
* It's agonizing slow, both on the client and server. The server is an egregiously-slow GraphQL endpoint.
* It hasn't been tested on anything but Chrome, as far as I can tell. It flat out refuses to work in Firefox or Edge, even fresh installations I've put into VMs. These browsers may not be mainstream targets, but odds are you would have no trouble supporting them if you weren't using these unnecessarily complicated client-side frameworks for placing a coffee order.
* It routinely messes up state management. I've had it forget my selected store location; fail to add items to the shopping cart; fail to submit orders; fail to apply star points (coupons); get into a weird state where it thinks I have a coupon when the server disagrees; etc. It's constantly introducing new and imaginative ways to fail.
* If you use it for months, white-page failure modes are surprisingly common.
Every time I use it, I wish that Starbucks had made just a plain responsive web app with simple server-side rendering. It would be fast and probably work better as a way to place orders.
I built out another product, which was much more dynamic and made sense as a SPA. However, having been bitten by the forced SPA, I decided to do as much static rendering as feasible, and I think that has made things a lot easier to develop and less buggy.
Honestly, I agree that a SPA is usually a bad idea and prefer to have as much of the app be able static as possible since that simplifies things considerably. For example, slack could open a separate tab for settings (and perhaps chat history) and only have the chat parts as a SPA. It would make it slightly less fancy, but also probably much lighter on resources, faster to load, and easier to develop.
Most of your complaints are about poor implementation but if a large percentage of people poorly implement SPA then it still looks bad. I used to say you could make a very native experience with a hybrid web app for mobile. While this is absolutely true, most people don’t pull it off so I get the critism.
I also disagree with the idea that SPAs are pushed by developers who have lost touch. Clients frequently push for them and ask questions like "Twitter/Instagram/YouTube don't show these blank white pages after every click, why does my site? Can't you make it like YouTube?" Clients want to have them more than developers want to make them.
I don't think I could disagree more with a statement, but the way I browse the internet might be different from the way you browse the internet. SPAs, when done correctly, create rich and interactive GUIs that absolutely bring browsing websites into a entirely new territory for UX. There's a reason why webapps have taken over, including desktop apps.
The reason I'm even reading this comment section is because I wanted something to do while waiting for Gmail to load.
When working with static pages that have minimal interactivity, sure. Just render the HTML and send it to the client.
Once you get past that though, if you try to stick with SSR you'll end up with incredibly difficult-to-decipher mish-mash of if/then statements, most likely with lots of jQuery or equivalent thrown in. I've debugged such templates and they are universally messy, not just because they are usually written by backend engineers who have a minimal understanding of/appreciation for JavaScript, but also because keeping track of state with such templates is really inefficient and frustrating.
When browser receives HTML, either complete pages or updated fragments of them, it only needs to parse HTML, style/layout, and render. These steps are relatively fast, especially rendering (usually GPU does that).
When browser received JSON or XML instead, it needs to do all that as well (parsing is slightly simpler), but also it needs to make visual elements out of the data. Takes a lot of processing and therefore electricity: JavaScript is not particularly fast, the code size is often not insignificant i.e. takes time to download and parse the code, and the runtime is essentially single threaded (for any given page).
It feels like browsers are closing the gap pretty well with things like IndexedDB, offline features, WASM, etc. Still a ways off, but seems like it's getting there.
I do worry, though, that it's not really in Apple's or Google's best interest to move that along.
The only positives are to corporations and institutions with profit motives to decrease dev time and increase ability to spy on users and extract rent from them.
I agree with slower, at least for computational tasks, but not security. Do you feel safer installing an organisation's native app than using their web app?
> The only positives are to corporations and institutions with profit motives...
What advantage does the web give to corporations that native apps don't? You mention spying, but the native mobile app ecosystem is filled with tracking and analytics code (and it's easier to hide it). The only corporation-level difference I can see is that native apps are heavily tied to a specific company's platform, while web apps aren't. This is a huge positive to the web - I've felt free to change platforms many times.
A second huge and underestimated positive of the web is backwards compatibility (ie. lower maintenance headaches). A complicated internal web app I wrote eight years ago is still running despite not being modified. The websites and lousy javascript I wrote as a kid in 1999 still run exactly the same as in 1999. Spacejam.com is unmodified from 1996. Yet I have many native apps from two years ago that no longer run correctly due to OS updates (especially on mobile).
Browsers are forced to implement standards like CORS, single-origin policy, and multiple levels of SSL certificate validation and thus are more secure than most of native apps. How do you know whether that mobile app is not signing in over HTTP? In a web browser it's obvious instantly.
> motives to decrease dev time and increase ability to spy on users and extract rent from them.
Literally the worse what can happen over web browser is tracking based on various forms of fingerprinting. Native apps? MAC addresses, SSIDs, serial numbers - EVERYTHING is available for the native app to send ANYWEHERE, even over HTTP.
v8 is probably one of the most strenuously vetted pieces of software on the planet.
Native is only a trade-off that has great performance at other expenses.
I mean, it's neat and all, but most websites aren't CPU-bound.
Coming from the .NET toolchain and expecting a lightweight, easy to start with approach I was yet again totally shocked.
The hundreds of possible directions you can go in, in terms of frameworks, packages and what not is ludacris.
I stopped working when my node modules directory topped 60mb and I still hadn't made a data layer.
Good luck fixing that. I'd rather keep my code and tooling simple and clean.
There are many options in the front end sure but when you just pick something and learn it then it is not very difficult to get started.
Just start with for example just React or Vue and don't add any state management. Create the apps with their CLI and follow the tutorials on their homepages.
Microsoft did a terrible job not having one framework for every path, like it did with the original .NET framework.
`node_modules` directory topping 60+ mb means nothing when the final product is an optimized bundle or a `node` process loaded in memory. A large majority of developers don't care about this because they're just looking to get actual work done... not sure why you're trying to "fix this".
I'm also not sure what you're talking about when it comes to unclean code and complicated tooling. The tooling is dead simple... much simpler than the NuGet/IIS/OWIN nightmare that is C# development.
I think you're very close minded and you'll likely be stuck in .NET land forever. And that's okay if that's what you like or if it's what gets you a paycheck. But to completely dismiss this ecosystem as if it's not productive... it's just a sign of naiveté. Good luck.
With WebAssembly, C# Razor Components will soon be able to run either server or client side and still maintain the same highly productive development that's missing from JS.
Writing your own http server is difficult in both.
Vue cli new project run.
New asp.net project run.
It’s identicle.
Try to write both for scratch is hard.
So no node/npm/http server is no easier than .net/iis/owin.
I may switch things up once WASM is further along. I would love to be using C# on both sides. I would still want very clear backend/frontend separation though.
> I stopped working when my node modules directory topped 60mb and I still hadn't made a data layer.
This is cute.
I have a 40gb virtual machine with Windows + VS Enterprise and SQL Server, that I have to use to work on a single .NET project that can't be migrated to .NET Core yet.
What is 60mb compared to that?
It's a bit silly to say you quit when you topped 60mb in your node modules directly, something you never have to look at and doesn't represent what gets built in to the final app. There's tons of dependencies when dealing with the .NET toolchain.
There are hundreds of directions you could go in, and I consider that a good thing. There are choices, but there are recommended paths for beginners as well.
It sounds to me like you're hating on a toolchain that you don't have any experience in.
No configuration of babel or webpack or whatever to worry about, just host your app as static files that point at your API.
It grew, as projects do, out of its original simple use case and now it needs to be usable in scenarios where network access won't be available for most of the work day, which means I need to rebuild it --in whatever time I can manage to devote to it, dev not being my primary or even secondary responsibility-- to deal with that and better handle the functionality we tacked on later.
After a review of my options, which unfortunately doesn't seem to include writing a native application (for reasons I still may be able to work around), I'm thinking that my simplest option is to just write a single page of JS that writes HTML to the DOM directly and works with data entirely locally, synchronizing it with a server API (.NET) when available. Basically, just a client application written in JS. No special frameworks, no complicated toolchains. Even that is a pain in the ass because the web world hasn't quite worked out how to store local data in a non-stupid way.
Also, .NET and “easy to use” hasn’t happened in forever. Unless you’re counting the “Hello world” tutorials that are useless.
The .sln file within a .NET project ends up being pretty damn large, so the whole 60mb node module thing seems a bit ridiculous.
I have my personal home page written as a Vue SPA. It was a silly amount of work to get together, and not everything works perfectly. BUT: it moves like a rocket. I pre-render the simple front page, so initial load is nearly instantaneous (especially with cloudflare &c), and, by the time a visitor finishes absorbing the information on the front page (which is just a palmos style collection of icons to other content), everything else is loaded. Which means that the effective load time of the whole website is perceptually indistinguishable from zero on a moderate-speed connection (like my crappy home DSL).
And that's... cool. It's legitimately cool. Let me have my fun!
No offense, but I don't know you, so I'm not going to run untrusted code you serve my computer without some good reason. That means your website is completely broken for me. It is also likely broken from an accessibility standpoint for those with special needs or using tools to access your webpage. (edit: People's personal browser defaults such as size, font, scrolling, language translation, or any other plugins they use for their workflow may easily break.) It also means that search engines and robots will have a hard problem indexing the links on your page or understanding the layout of your site.
So while I could agree you've created this cool user experience for the most common case, it breaks the fundamental precepts underlying the web and I think this does have some negative consequences, especially if this became the default approach. That all said, you do your thing - I just hope this provides useful food for thought!
Today, not running JS breaks the web. You can lament this, I too think it's not ideal, but you can't change it. So don't accuse devs of breaking the web for using an SPA just because you're part of the 0.002% of users that doesn't run js by default.
Furthermore SPAs do not break accessibility, that is nonsense. Devs may break accessibility if they choose to reimplement components without thinking about it but that has zero to do with SPAs.
No.
It's a perfectly valid point to make: splitting everything up into SPAs, micro services, etc, instead of solving the business problem with a monolith is indeed the wrong way to go, and Martin makes some sensible arguments around this topic.
It's the same in video games: you create a prototype using cubes and texture-less blobs to test the "business logic" (mechanics) first before you produce a AAA model and 700 animations.
I do like the big icons on the homepage and I'll just say great job.
You used an spa because it was easier for you and that makes sense. One npm call and oje starter kit can get you a finished emtpy app. Doing it in plain html should be even easier but we lack the all-in-one modern tool it seems.
No criticisms here, just observations on what gets missed generally by people who go too far along the build tools path and overlook things like document structure along the way.
The actual document could benefit from HTML5 niceties such as more accessible elements than 'div' and the table elements. Table has its place but the world is moving on to CSS Grid for proper layout of content rather than tables. I prefer to see 'article', 'section' 'aside', 'nav' and even things like 'cite'. For added usefulness to Google a few structured markup snippets for all of your publications will help nicely. The schema.org 'article' is a good place to start on that, you can also render your HTML from this structured data if in JSON+LD if you insist on clever wizardry or just put the Rdfa (or whatever) tags in the HTML.
The UX is not truly accessible, the home button is not a good touch target size plus the navigation is against the 'don't make me think' principle.
So it might 'move like a rocket' but if the site visitor can't work out how to get the navigation then what is the point? A vast magnitude of time is lost.
A favicon could help with accessibility too. If someone has lots open then a tab identifier helps. Go through the necessary to make a PWA instead of a SPA to get that right - nowadays you need lots of different things for 'add to homescreen' and whatnot. Whilst you are at it include some useful metadata in the header for people sharing your page on social media. Set the meta description with 'nosnippet' so Google shows people exactly what you want them to see. Nobody sees your site before Google so it is important.
Sometimes a focus on gadgets is counterintuitive, so the inline SVGs base64 encoded might be very clever, but to someone that understands SVGs this makes no sense at all. They are better as document content, not in an img tag and not base64 encoded. They will compress better that way too.
If you did the SVGs normally then you can use currentColor to effect a mouseover, you can use their title tags to show some text on the mouseover.
Also, writing an SVG as something like this:
path d="M384 1408q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm0-512q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5h-1216q-13 0-22.5-9.5t-9.5-22.5v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zm-1408-928q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5h-1216q-13 0-22.5-9.5t-9.5-22.5v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zm0-512v192q0 13-9.5 22.5t-22.5 9.5h-1216q-13 0-22.5-9.5t-9.5-22.5v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5z"
is a bit bulky when what you really need for that is to do (pseudo svg here) 'group fill=currentColor stroke=none id=circle-and-line' [ 'circle r=[radius]' 'rect x=[origin] y=[origin] width=[width] height=[height]' ] 'use y=[minus-a-bit] href=circle-and-line' 'use y=[plus-a-bit] href=circle-and-line'
In that way you can get a super concise and super editable icon for your CV that you can edit and tweak in document. It will also have the currentColor niceties. Sometimes I think that just because you can put sausages in a blender doesn't mean you should. Those SVGs really are wrongful being inlined and base64 encoded when HTML provides perfect and better mechanisms built in for doing whatever it is you are trying to achieve with them. Also, SVGs are best hand drawn for a pet project site, internet SVGs are just the disgorgings of an Adobe product, normally shapes for icons can be drawn with rectangles, circles, polygons and lines specified with integers, the Adobe products use NASA numbers instead (none decimal places).
I would say that you would have a lot more fun if you got the basics of document structure, accessibility and awesome SVG goodness done right, with measurables in Google search results and eyeballs.
We all live in glass houses and I am definitely throwing stones here with this critique, but the web gets better with a little bit of discussion on these things.
(But, to the original point, all of those great suggestions are totally compatible with doing things SPA-style. And actually, Vue components are so composable that these kinds of changes should be pretty easy when I get around to them.)
Yes, a nice state machine-like flow with each thing happening only once at a given time is great, right until you get asked to make it so that clicking on a thing shouldn't reset all user input, and progress of a task should be communicated live, maybe while we also we want this app to just not show a blank screen like, ever, just comes and happens to you and that's what you kind of have to do now.
Website != Browser app != Mobile app != Desktop app != AR/gaming platforms
If you know which of those you need, you can make an optimal technology decision. No one can expect to turn a wood-framed structure into a steel-framed structure. Nor build a steel-framed structure for the price of a wood-framed one.
In this day and age, chances are better than not for anything reasonable involved, that this smooth interaction is a business requirement, but YMMV.
...what?
> continuous saving
No problem.
> and all those nicely choreographed state transitions
Learn to say "no." It works wonders whenever people tell you that your aircraft has to go under water now.
Like if you're doing SSR you could at least use something like turbooinks to implement state transitions.
Good luck keeping that client after the end of your contract.
BUT — with a bit of work, you can set things up to do server side rendering. It requires you use Node at some point in your server stack, and you essentially call the library (on the server) and run their RenderToString function (each has a slightly different implementation).
There are frameworks for this (next.js, nuxt.js) or you can roll your own - it’s not terribly complicated.
As a predominant back end developer, I do feel that the complaints from the article are due to inexperience or misunderstanding:
1. stateless requests: You don't have to cache any state by default, just like server side. You start caching to improve performance and caching is always one of the big 2 problems of computer science. Don't cache if you don't have to: stateless has benefits.
2. Reinvent browser features: use your framework! This is a solved problem. I am not sure what the Angular or React solutions are but with vue just use the vue router.
3. More mature tools: backend suffers from this as well, I know a lot of mid level software engineers that are always chasing the latest fads. Microservices, containers, serverless, etc. The biggest issue I had when I tried to do serious frontend development is just not being aware of the tooling and how it works.
4. SEO: Google can crawl your webapp: https://searchengineland.com/tested-googlebot-crawls-javascr..., I would prefer if the person making the claim (that an SPA does not get crawled) would be the one providing the evidence...
Don't get me wrong though. Sometimes an SPA is the wrong choice but it would be hard for me to say if that is usually, rarely or a toss up.
I think many places that go from server-side rendered to client-side rendered SPAs do not hire a bunch of front end experts when they do so. Then people experience a bunch of problems because of the fact I point out in 3: lack of awareness of the ecosystem. On the other hand, there sure are a lot of diva developers who don't like working with old technology (for example, PHP), and this probably causes a lot of the front end framework churn. Just like picking up a new language, it takes time to produce idiomatic code. Of course, for a new framework it takes time for the idioms to develop...
Here is the talk: https://www.youtube.com/watch?v=PFwUbgvpdaQ
For React there's a couple, but most of them boil down to the same basic idea that you've got switch statements that decide which components to render based on router state (rather than there being anything "special" about routing entry points), and then something like a <Link> component that just acts like an <a> tag but triggers the client routing change instead.
- Timeout error / no network connection
- Ability to stop requests
- Show that the browser is sending a request
Also, in the favor of SPA's you can consider the horrible state of repeating post requests when users press the back button on server rendered multi-stage forms (like purchasing a flight ticket). Of course, you can just avoid implementing multi-stage forms via POSTs like this and I wish airlines would stop.
If you implement your SPA with a service worker and use cacheable GET's properly, your SPA can work offline and survive temporary network glitches (like on a train) in a way that server rendered apps never can.
1. Reusable web components. 2. Clear separation of backend and frontend logic. 3. Using the latest version of javascript.
I really like HTML/CSS/JS as tools for building GUIs, but I feel HTML/CSS specifically suffer from the inability to make components.
I think there are definitely instances where there is no need for these tools. I would genuinely like to know how to manage the items listed above when this is the case. ie Recommended tools for when I go "SPA seems like overkill for this... what are my other options for this functionality?"
They offer a ton of advantages, especially speed of development if you have a clear separation of frontend & backend logic. If you can mock your backend & develop the front end all by itself without any other code needed, you can go at crazy fast speed. You are also able to focus on UX/UI without needing to think at all about the backend. I feel there is a ton of value in this, whether or not your app is a SPA or not.
I think tools like Gatsby will make building actual SPAs easier down the road. They offer huge speed advantages the longer someone is on the site. Though one could gain a lot of these with just preloading content & HTTP/2 as well. As the article said "It all comes down to tradeoffs". I would also argue what resources you have available & the value of speed on your site.
Are you familiar with CustomElements? https://developer.mozilla.org/en-US/docs/Web/Web_Components/...
I don't want to say you should use SPA frameworks for anything, don't make your company website with SPA. What I want to say that if you have a complex process you can consider creating "enterprise" UI instead of trying to dumb it down to a series of billion simple forms.
If you feel your business is overusing SPAs (is it so strange they want new shiny toy?) then as the technical person you need to educate them on pros/cons of the technology.
It's not complaining. It's a profession's view on the state of (default) behaviour by most developers in the wild. It's a valid set of points as to what the default mode of operation seems to be, as a general rule, and why it might not always be the correct default mode of operation.
I personally feel like what's really missing here is something like a generic spec (not a generator, but a descriptive standard) for the structure and organization of CRUD-style JS/JS-derivative SPAs, something like what re-ducks (https://github.com/alexnm/re-ducks) did for the Redux world.
Server-Side rendering tightly couples your front-end to your application server. Scaling the site means scaling up that application server. A bug in one "page" of the app can cause the whole application server to go down.
If you leverage client-side rendering then it's easier to decouple your front-end from the back meaning you can take advantages of things like segregated micro/serverless services and progressive web apps. You can also re-use those services for multiple applications, making it easier to keep the business logic OUT of your pages and in an API layer where they belong.
I agree that SPAs are not the solution for everything, but I think that server-side rendering is on it's way out.
That doesn't seem like a valid issue. If a bug in a single page could take the application down then the same could be said for the API powering the front-end.
> If you leverage client-side rendering then it's easier to decouple your front-end from the back meaning you can take advantages of things like segregated micro/serverless services and progressive web apps
Your PWA point is valid but I don't think the microservices point is. Microservices add a ton of complexity and can easily become overwhelming. If you get to the point where your application can benefit heavily from microservices then congrats, you've made it.
> I think that server-side rendering is on it's way out.
If anything I think its on its way back in. So many companies bought into the benefits of client side apps and are now seeing the trade-offs that aren't very favorable.
Maybe if you're using node or some other single threaded server like that but this isn't true for multithreaded or multiprocess servers. It might be an argument against node but it's not an argument against server side rendering. Also, it's irrelevant how pages are rendered or what you're architecture is if a bug brings down the whole server--either way your app doesn't work.
For example the server has to send a tag with a class name that the client also is aware of that.
Therefore you have 1 component, where half is on server side and half of on client side, which in my opinion is not maintainable.
Especially in news, articles, longreads, right? /s
Most of the internet content would be perfectly fine without interaction, or with ordinary, oldschool POST forms
One day I just ditched the SPA and rebuilt the whole architecture with NodeJs and Express. I was done in a few days. It could have gone even faster, but the original static site was really a mess with years of accumulated bad decisions embedded in it.
I know this is just one data point and not really proof of anything. Nevertheless, the linked article made a lot of sense to me. Most of the bulleted points resonated with me, but none more than the SEO issue. There are solutions to the SEO issue, but I personally did not find them easy to implement. If I were part of a big professional team, and we really needed a SPA, I would have called this one differently, but I was working on my own, and I didn't really have the sense at first to see that I didn't need a SPA to achieve my goals. I was perhaps a bit too susceptible to the hype without enough experience to really understand the issues involved.
You get streamed JS, with pre-rendered HTML for SEO.
This article says traditional web servers are stateless, but in the case of SPAs servers are stateful. The opposite is true. Traditional web servers have session state, but in the case of SPAs the servers can be stateless because all servers are responsible for is persistence and query/search.
This article says maintaining browser history is a mess in SPAs. Not true. The same MVC architecture that works so well on the server can be done just as easily on the client, see this lib: https://github.com/Rajeev-K/mvc-router/
This article says server-rendering has fewer more mature tools. That may be true. There are so many new tools for SPAs. But you can ignore them and build SPAs trivially using the libs mentioned above.
This article says server-rendering is better for SEO. Not true anymore. Google and Bing crawlers now execute javascript to crawl your content. This is more work for Google and Bing but not more work for you.
If you know how to do it SPAs are the easiest and best approach because all the server needs to do is implement persistence and query/search using a REST API. If you later need a native mobile client this approach is already more compatible with mobile than if the server renders HTML in addition to persistence and query/search.
Not sure about "easier". I'm a backend person so take this with a grain of salt but, to me, nothing on the web is easier than doing everything server side. All of your code can be in one language (plus a template) and the same build.
Consider what it takes to make a change in each model. In an SPA with one of the frameworks mentioned, it requires several changes, across directories and languages in both the front and back-end, and usually two different build chains.
When you follow the redux (or whatever state lib) flow you prevent a lot of these issues.
Libraries like React are awesome for breaking down complex (or even not so complex) UIs into story sized chunks that can be tackled by different engineers or even different teams. This is one of the biggest reasons to consider using them, IMO.
Even in the case of relatively unremarkable CRUD application, if the backend is split across multiple services and teams it may be entirely reasonable to choose to build a SPA frontend with a dedicated team.
On the other hand, if you're building a Rails app with a small team, and most engineers are working full-stack out of necessity, a SPA may not be appropriate.
As companies grow, I've found roles tend to become more specialized. Your decision to build a Rails web app early on could be considered legacy cruft (by some) down the road because it can be difficult to break down and deliver a feature across the full stack if you're not accustomed to building web apps that way.
There are tradeoffs to all of these approaches (including the hybrid approach). Ultimately, you need to do what's what right for your product and team(s), and make your technology choices intentional.
And the users.
Conway's law: "organizations which design systems ... are constrained to produce designs which are copies of the communication structures of these organizations."
It’s a totally different question to ask do I need a spa or a server rendered app, both can be dead simple or heinously complex or reasoned away to prove a point...
I 100% of the time want (1) to architect my UI as a collection of atomic, reusable components, (2) get page specific server rendered html per route, and (3) do JS in a sane way (manipulate DOM, manage client state, and support a series of interactions that do not reload the page.)
So, what are my options?
1. React/node 2. Sacrifice one of the above.
The other problem is deciding which to use when starting a new feature or section. A page may start out fairly static but end up needing a rewrite when the specs change and start requiring more dynamic UI elements.
Use JS rendering for all your pages but continue to use Laravel for routing/passing data to view: https://reinink.ca/articles/server-side-apps-with-client-sid...
To show how long it's been since I've done front end...My last 'full stack' development had plenty of tables to style the application grin.
Progressive reveal patterns are expected by end users. It's just lazy for a programmer to assume old-world CRUD patterns with server-side render.
The current culture is to only keep a job for ~2 years before moving on, why wouldn't they adopt that attitude?
The message is build with what accomplishes your goals and works with your team's skills.
The notion that SPAs are only good for certain types of applications or organizations doesn't make much sense to me.
Building server-generated web sites works faster for me because I'm still more comfortable with it. SPAs make concessions but so do server generated apps.
Unfortunately most teams cannot be trusted to pick the right tool for each job without overcomplicating the planned implementation. Ego and the yearning to do “cool stuff” conspire to derail projects that could have been built without fuss using simpler tools.
Let me give you the simplest possible example. A form with multi-dependant inputs: you select an option from a dropdown, and depending of the choice you made, you see another dropdown with some options, or maybe an entire new set of inputs. Maybe there is a button that will open a popup with another form, dynamically generated based on what you choose. Or maybe there is data you must dynamically fetch from the server, based on some combination of actions that the user did.
You can play the ".show()" and ".hide()" game with plain JS, but if you have more than 5 inputs, I promise you, you'll be really sorry for choosing that method.
You can also "inject" somehow any SPA just into that particular view in your project, but then you'll be already dealing with the cons of both SPA and SSR. It doesn't pay off.
I have been doing all types of FE and BE development, and what has given me the best results is making the BE a REST API and doing the rendering on the frontend.
Just my 2 cents.
I use Rails, but Rails views are a disaster. You can use a lot of different patterns/gems, but still, logic is highly coupled with the view layer. Personally, I like Phoenix approach with templates + views. But still writing script tags makes me cringe a little bit.
But I wouldn't discourage people from using SPAs, though. If you are gonna have a lot of buttons, modals, different tables, charts, forms and stuff like that, I would go SPA. Or first serverside -> SPA. Especially, when you are working in the team, it's so much easier to tell one person to craft this json api and another to craft this design with a consumer for the json api.
That become long... in short: if you have a small team or solo go server side 99%. If you have a big team or app that's gonna be very heavy UI -> go full spa or go server(mvp) -> spa
Just as a SPA won't solve all your problems without any trade-offs, getting rid of a SPA framework also won't solve all your problems -- you'll probably need to re-invent some wheels and then discover that your new solutions are hard too.
I think it's good to have a healthy dose of skepticism about new technologies. But it's also important to understand their value and not to hate them just because they're hard. I like that the author tries to find this ballance. Though, honestly, from my own experience, I would rename this title to "You might not need a single-page app."
More than once, I've tried to build something without a SPA framework only to realize that if there is any interactivity at all, it's often just simpler to use a SPA framework in the first place.
Simpler or more convenient? I've yet to see a production-grade React setup (for example) that is simpler than having either vanilla JavaScript or even jQuery to achieve the same interaction. The amount of tooling required to do simple interactions does not justify the technology for most applications IMO.
Or nosql.
Or containers.
Or graphql.
Free tech is not zero cost tech. Size your stacks to your actual needs.
But in reality...I only need it because people on the other side of the interview table expects every engineer to have 3-5 years experience of x,y, z.
I agree that the hybrid approach of both server-side templates and SPA-controlled content looks difficult.
On the other hand, to get your Rails site to function that well takes a lot of work - it is by no means the starting point.
Systems like Next.js and Gatsby.js and others are attractive in that A) they offer the ability to use both server-rendered and client-rendered React, and B) exceptional performance is the starting point. It's up to you to slow it down, not speed it up.
Since I work alone I suppose I'm not up to speed on what defines a single page app but the apps I've been building with PouchDB, jQuery, and Bootstrap run in a single page.
"Stateless requests Traditional web servers are built to be stateless. "
True, but "apps" should be designed to be self-contained (i.e. all the user navigation is done within the app UI, not the browser UI).
"The browser knows how to deal with a traditional architecture If you go with the SPA route, you’ll always need extra code to emulate trivial browser features."
That's a pretty trivial problem and browsers don't really solve that, nor should they.
"Fewer, more mature tools Avoid the Javascript fatigue by not relying so much on Javascript!"
The apps I'm building are almost entirely Javascript. I see that as a good thing. What little I do on the server side I do with Perl, which is something I've been doing since the `90s, so I can feel "traditional" doing that if it helps me sleep at night.
"SEO for free Single-page apps have to add extra infrastructure and code to make sure they can be indexed by crawlers."
This is not so difficult to address and in some cases it's not even a consideration. In the case of a "blog" app you can simply assign a url to a post and deliver a page built on the fly specifically for it. Google can parse that.
Not sure if that's what you mean here, but when this breaks the “back”, “next”, “refresh”, “bookmark” or “share URL” features of my web browser (among others), I hate whoever has been responsible of the design as much as I've hated Flash in the past.
React was introduced in 2013 and angular 2 was created in 2015.
The only server side rendering I'll be doing in the future is with the likes of nextjs or similar.
Now you have two problems.
What are some elegant strategies for handling this with SSR?
I’ve used turbo links and found it rather clunky. Haven’t seen a solution that lets me elegantly reuse server side components in JavaScript without going SPA.
What ? These are all javascript things, right ?
SPA approach should be the default unless you have specific requirements to add html SSR (and even then google is pretty good at indexing public spa content too).
So, respectfully disagree.
With a server rendered website, you don't have to do anything
MVC is a mistake. Read that again. MVC is a mistake. It's not a good paradigm to write web applications in.
SPA's are not complicated. They do not take longer to build. They defacto are often way more responsive than any server side monolith that gets built. Because developers who buy into an archaic and broken "MVC" systems typically do so because its "easier" for them, but it's easier because they're not willing to think about whats being written in the first place, and that's a recipe for a bad app no matter how you write it.
Inevitably you will end up hacking your "simple" MVC app to meet perfectly reasonable, ubiquitous client requirements regarding user experience. Because the paradigm isn't fit for base level requirements.
A few years ago my entire job was completely based around consulting for these types web applications. Inevitably you get these developers that think they're wise by going "we're just going to do it with MVC" -- and after a few months of use it becomes completely obvious that the dev team can't meet any kind of modern requirements for the web application. The existing web app is slow (but it's "fast" to the developers), buggy, and the worst part for the business is it takes forever to write features for. Eventually these companies get so frustrated they look to the outside.
To recap, when you build a "traditional" MVC app this typically means a few different things:
1) It's written in a toolchain that's fairly niche to "back end" developers; severely limiting the pool of talent that company can hire to maintain the web application moving forward. In a fair number of cases the company will have a front end team and a back end team. And sometimes all that back end team does is update views so the JS developer can do their thing. So expensive for something so small.
2) You will end up writing a mass of JS anyways, but the JS will mostly revolve around dealing with the fact that the server side templating language controls the original output of the web application. At worst, this means that a lot of devs like to sprinkle bits of HTML inside the JS. So now your templating is strewn across multiple languages and locations. The JS is typically bad because these are "real" developers who don't like JS.
3) Because of 2, there will also be a mess of server side code purely written to massage data into the server side templating language and an analogous set of code just for the JS side of things.
4) Because of 2 and 3, the app because buggy and oddly slow (though again, the devs that wrote it will only look at the original output timing and not the actual life time performance of the application).
5) Because of all of the above, the company has now spent an enormous amount of resources for a fairly shitty app that no one likes to use nor maintain.
My primary focus for these companies was to build a baseline SPA. And then over the next couple of months guide them through creating new features.
And this wasn't a one off thing. I had an entire job based around fixing the sins of the company's internal developers who are costing the company money while not delivering, costing the company money making the application way more complicated than it needed to be, and costing the company money by forcing the company to hire a specific subset of developers familiar with their MVC toolchain.
Stop circle jerking about MVC apps. They were ugly in the first place and continuing to claim that's how we should build web apps is an erroneous position purely fueled by stubbornness on the part of developers.
Here's my benchmark for an SPA: You can either build your entire site using static generation, or you need to structure your web app as an SPA (or prepare to do so in the original implementation). That is the threshold in the current landscape. If you can't get away with doing a statically generated site then you're not going to have fun writing your site with backend MVC framework. At the very least the company's finances definitely won't.
Actually now we are full circle again. Files that mix css/template/logic with FOTM syntax, add some database calls during SSR and you have basically PHP. Just more complicated tooling. Deploy your frontend on S3 and its similar to FTP to Apache Servers, except you can‘t update just individual files. Run your backend on AWS lambda and you have stateless backends like ... PHP, but with cloud vendor lock-in. State Management like „Flux“ that poorly resembles state machines on top of JS shortcomings.
I am personally switching completely to elixir/phoenix to do anything web-related and can solve things cleanly within minutes. Also when Phoenix LiveView finally arrives, it could be groundbreaking and replace many usecases of modern SPAs.
It also makes testing dead simple: you just make contracts on what the response bodies will look like and just feed mock data structures into your stateless web app. This allows the API team to make changes to the API layer with confidence that as long as they don't change the contracts with the web app, everything will still work.
2) Complex webapps with snappy functionality that need to feel "native" - whatever that means: think about an SPA. Then realise that mostly what you need is (1).
3) Corporate homepages / brochure sites / product sites / blogs: use a static site generator like Hugo, Jekyll etc. It's amazing what you can do with a staticgen site now
[Insert shameless plug for Trolley, my product, https://trolley.link ]
We're getting closer to the best of both worlds, where we SSR pages and then "hydrate" them with JS components. The tooling around this isn't great yet, but it's definitely all there.
2. "You don't need the complexity of SPA or javascript fatigue" and then you install webpacker gem that wraps around webpack and not only you have a headache of webpack but also of a gem that wraps around it. And then you need some front end libraries and you start including them in in the way that feels like a workaround.
I mean no disrespect to these wonderful tools, I appreciate the hard work being put into these gems, and I will admit I didn't give it TOO MUCH effort to learn. I tried it. didn't feel right. moved on.
I've just decided for myself that for now I'm gonna keep my backend ( ruby, db, server ) in one mental bucket, and all the fronted ( css, js, html ) in another.
For me to go traditional Rails way it has to be a super simple app, at which point there will probably be other tools to solve the problem.
Not only the complexity of development is increased, but there is no real benefit for the vast majority of use cases.
I think there is merit in using an API though and clearly separating data from presentation.
What I've been doing lately is using Jekyll with Vue components for some in house projects. It works great.
Another option I've been trying out is doing SSR in JavaScript on Zeit Now monorepos. Haven't used it in a real project, but so far it's awesome. You can keep using all your front end knowledge, but render each route on the server. No more managing state (Redux, Vuex, etc) or router.
With SPA's, you're usually dealing with some build system, a variety of dependencies, and a swathe of design patterns. At worst, you have everything located in a single file which has all of the above across tens of thousands of lines.
With server side rendered code, you are (at worst) following someone's code that didn't follow the correct separation of concerns. At worst, the spaghetti code will be within a couple thousands of lines of code.
I had a project recently where I ran into both of the above scenarios and I would prefer to debug poorly written server-side code than poorly written SPA code. It's night and day in terms of complexity.
Laravel is stable in production but they break backwards compatability all the time and not always in major versions.
Symfony is much better about it.
(Sure, we could've gotten similar performance with server-side rendering, but at least with the current state of SSR tooling that would've been way more distraction from building our product than we could justify.)
Most applications don't require these frontend frameworks, and it just adds needless complexity in most cases. I've suffered due to this, and so I've recently made the move back to server rendered apps.
And Rails with Turbolinks + UJS might not perfect, but it gets you like 80% of the way there for 10% of the effort.
Most websites are best served by serverside rendering. Or some form of hybrid where you only send the templates as JS that will be in need.
With SPA’s what usually ends up happening is that the whole app is sent in the first load. All the views, their css and shebang. <1% is actually used by the browser. This is where most hate comes from. Most people give a shit about “time to first meaningful paint”. It’s what makes up for that “wow that was fast experience”
You can optimize both SPAs and server rendered pages for ttfcp. The former requires a lot more discipline.
Browsers also do a lot to render as quickly as possible without the whole page being downloaded. With html it’s simple and they have a lot of streaming tricks.
JavaScript is not that simple. It blocks the eventloop and the payload is downloaded in full, executed and then a paint can happen.
There are trade offs. SPAs can offer high interactive experience when server side rendering cannot.
SPAs are great. Just don’t throw everything away. We need the baby.
Component-based views are starting to get to server-side frameworks so that should reach parity within 2 years and WebAssembly will change the rest. Now apps can be built using many different languages with OOP/functional styles, strong typing, dependency injection, etc, and run at native speeds in the browser. With the next gen of WASM running threads, GC, and DOM abilities, JS frameworks will likely start a slow death as the existing web frameworks start to have both server and client side delivery models.
ASP.NET Core with Razor/Blazor is a great early example of this: https://www.youtube.com/watch?v=Qe8UW5543-s
At https://qbix.com/platform we wanted to stick closely to the Web standards so we built a hybrid - although new pages would be loaded with AJAX, out of the box we made the “easy development path” cause every to page load from the server. This was because back when we started, search engines and other crawlers didn’t execute Javascript very well.
We always kinda felt bad that we didn’t “fully” embrase the “new and best” SPA trend, but also felt good we were giving people choice and were more compatible with Web Standards. And now as time goes by I see more and more of our choices vindicated. Is this anti-SPA backlash just another fad? Or were we right to give people two ways to render the same page - one on dynamic navigation and one on refresh?
Yes, building a SPA is not always the best solution, but sometimes I get the feeling that a lot of developers hide behind 'I know how to build good SSR pages and all SPA I have used suck so I will not learn that sh*t'. If you know how to build a PWA with SEO support, offline+sync capabilities and push-notifications, you will know when to choose what (because of the pain you experienced learning it).
If your boss chooses your tech (from the latest buzzwords) and he doesn't understand the implications, I am truly sorry for you, but don't blame the tech on it (ask your boss for a seminar on 'How to Communicate with Managers' maybe then he will understand that you are trying to tell him something...).
- Web-tech front-end for an embedded device. The device, which often has very limited CPU cycles, is not burdened by rendering.
- Apps that are intended to be running locally and on multiple platforms (e.g. via Electron), as well as in browser.
I'm happy with building SPAs where it makes sense (myaccount/admin). The problem is Javascript and its ecosystem but you could very well go with Ember which is stable as...and be relevant for years.
We pretender enough so if you turn off JavaScript you get old school and if you turn on you get SPA. All the basic widgets are server/client agnostic, and we have a combinator to special-case the server vs client code when needed. The types enforce client-specific functionality isn't used otherwise.
We also have a "DOM puppet" backend which allows everything to be compiled to native code puppeteering browser APIs from a fair. Prerendering, that, and direct JS output all all supported through related typed abstractions. Soon we will compile the puppeteer to WASM too, so we won't even need the direct JS output anymore.
Native mobile UIs are great, but something as simple as cookies / local storage could allow for stateless (or at least less stateful) mobile apps with native UIs.
Now, the abomination of hybrid (cordova), or pre-processed (react native/xamarin) mobile apps is whole other thing, but often why web apps are translated to SPAs.
If we need a mobile app as well, why not use a common code base for web and mobile...
* to continuously play media (video/audio) while the user interacts with the web app (think modern youtube, soundcloud, spotify web, video news sites) * provide offline usage/features * highly interactive app with extensive use of drag'n'drop, animations, touch events etc. * data sync between browsers/tabs (think moving a ticket in a trello board should update the stacks in other open trello tabs or even for other users that currently view the board)
JAM-stack etc. just create static html/css/js and deliver it over a CDN of your choice, then hook into the services as you need them...
- Need for a mobile app is close on the roadma and there is an opportunity to build server code in an API first fashion.
Given all the complexity of managing multiple pipelines for simple and complex pages, it seems to make sense to avoid that complexity by adopting a single pipeline that ensures browser compatibility, testing, i18n, accessibility and performance optimizations are consistently applied and centrally maintained.
Which might imply , if _any_ of your app requires complex presentation/interaction, it might be better to just build the entire app using the same framework.
Unfortunately, even if your app doesn't currently have complex functionality or interactions, doesn't mean you can guarantee it won't ever. Investors are known for pushing products to innovate, pivot, and adapt. Which implies that avoiding SPAs is a privilege for app developers and teams who have absolute control over their product and won't ever be forced to build more complex products.
The Op also doesn't address how having frontend dedicated ecosystems might affect hiring, or influence performance. I remember the days of having 20 instance variables set within a rails action and each of them being deeply coupled into the Erb template. Having a clear client server separation at least forces one to use an API, which can make caching easier by separating the caching of presentational and data elements. Also, the semantics of each server side templating language are quite different. E.g , slim vs liquid vs haml vs ejs. Using server side templates requires frontend developers to be much more versed in both templating languages and understanding the tiny bits of embedded server side code. I don't imagine too many front end folks jumping to learn scala, clojure or Haskell. However, if the client and server are separate than that means a scala shop can focus on the API and hire a frontend dev with no experience in the server side stack.