Architecture no one needs is server side templating
itnext.io
itnext.io
I beg the author to deal with a typical real world application. Not low scope startup stuff but the thousands of 500+ endpoint typical enterprise stuff that 80% of the market actually comprises. This does scale out to the startup and web stuff as well.
This approach introduces a lot more pain from experience:
1. Having to maintain and upgrade SPA type frameworks is hell and you have to do that sometimes (think Angular upgrade hell). Can't afford to start again every 5 years.
2. The performance, and the article actually states it, is shitty at the best of times. All it takes is one client running mandatory IE11 on Citrix and you lose a customer.
3. Most of the complexity is hard complexity that has to be there to process rules. Rules are way more complex than you want to run on a client in some cases.
4. They are incredibly difficult to test. Go try testing a big SPA with selenium for example.
5. Security boundaries are terribly difficult to enforce when half of your application isn't inside your control.
Having done desktop development for a number of years, the worst turds I've seen are in that space and the SPA brings them all to the web which is one of the most hacked up evolutionary disasters we have ever created.
Really our responsibility as engineers, architects, developers is to give the user the best experience and that means the fastest and most reliable one. SPAs are neither. KISS is a mentality we should be using and I can build a better user experience without SPAs.
Greg Navis knows what he's talking about.
It’s an SPA, fantastic documentation, customers love it, and there’s an LGPL version of it.
My point is not to get you to use it - it is more that SPAs can work and work well in enterprise settings and for both dev teams and users.
PS: testing it with selenium is really easy - there’s a piece in the docs on how to do it :)
As for testing with selenium it's more the point that the entire thing is stateful so the user journeys are much more difficult to program which leads to horrible test coupling as you scale the suite out.
I suppose you have to ask: Do you have 22,000+ test cases?
Yes in some cases we had lots of test cases. But that’s just a result of the sophistication afforded to us. Yes SPAs enable the sophistication but citing that as a weakness is like claiming that a car is worse than a horse and cart because there are more mechanical parts that can go wrong!
Now right-click on the grid headers and change the grouping, add a frozen column. How many unit tests is that?
Now go here: https://www.smartclient.com/smartclient/showcase/?id=userDef... and edit some of the hilites - again how many unit tests?
Now, 90+% of websites and webapps don't need this type of function. Enterprise use cases (especially for things where users are coming off of Excel sheets and the like) absolutely need this sort of stuff.
But the performance was so bad that we threw it out of the window at evaluation time and wrote our own very light weight augmented view components which provided exactly this class of functionality.
For example, we render a bog standard table, then decorate it with some javascript which can collect a composite part of the table if there's a change of state. Basically a partial page refresh.
The code is tiny for this, the first hit is the view that the user wants to see with no RTT, minimal script load time (we use jquery to attach event handlers and that's it). After that we just suck the changed part of the page body down.
Fancy a 50ms RTT to a page hit? We do that.
Hacking around with the DOM is just not fun - and back then every browser had its own set of quirks. Personally the approach you took probably required as many unit tests as an SPA unless you only had to support one browser for a very limited set of functions.
The rest is not even wrong.
Please elaborate. Your rude dismissal is not informative.
> 3. Most of the complexity is hard complexity that has to be there to process rules. Rules are way more complex than you want to run on a client in some cases.
I don't know how to address this since it doesn't depend on the boundary of server/client code split.
> 4. They are incredibly difficult to test. Go try testing a big SPA with selenium for example.
This is highly application and framework dependent. Not all SPA apps in all SPA frameworks suffer from this problem. We are using different testing frameworks and we wouldn't say we have any significant issues.
> 5. Security boundaries are terribly difficult to enforce when half of your application isn't inside your control.
Backend doesn't change if you are fully server rendered or fully SPA. I don't understand how this applies in general.
> Having done desktop development for a number of years, the worst turds I've seen are in that space and the SPA brings them all to the web which is one of the most hacked up evolutionary disasters we have ever created.
As I mentioned before, the difference is that unlike desktop development SPA world is still evolving and there is no thought leader in how to do this. If we were given back in 2012 a definitive framework with all build tools in place, that would look like the typical desktop framework. However, we are spectators in this evolving space. That is the nature of open development and open source. Compare that with WPF, WinForms or any other Windows platform UI development environment.
> Really our responsibility as engineers, architects, developers is to give the user the best experience and that means the fastest and most reliable one. SPAs are neither. KISS is a mentality we should be using and I can build a better user experience without SPAs.
I disagree with this, it is a general statement.
This is not how React or Angular (or Express) works. Only the stuff that is required per-route (or whatever state) is "rendered" server-side. The rest is chunked away and retrieved when needed. From my experience, express rendered react apps never take longer than php / whatever rendered sites, given the data dependencies are retrieved from the same source (api, db e.g.).
Yes, the whole page, which includes the header, footer, menus etc.. What's your point here? I don't get it.
I Beg to differ, or at least add more perspective. I've noticed a trend over the past few years at large (>1$bn revenue) b2b and telecoms companies; teams in those organisations working on newer projects or initiatives start with the premise that the UI will be rewritten again in 3-5 years, and design accordingly. Maintenance concerns of that part of the project, for good or bad, melt away.
It's really not efficient throwing everything away every 3-5 years.
10 years is minimum cycle IMHO, possibly longer now that standards are relatively stagnant allowing incremental improvement. That's the point at which you can recoup the retraining investment and cover the hardware cycles easily.
At the end of the day the purpose of the software is to deliver a benefit and churn based rewrites pretty much pause all comprehensive development projects. They have no business value.
Whenever I do client-side stuff, I need to agonize over what libraries to pull in, and consider the api endpoints for data I need (and of course all sorts of security issues surrounding that).
This approach introduces a lot more pain from experience:
"From experience" — that's the thing. "YOUR" experience. As a JS DEV I've experienced a lot of good and bad examples. When things are done right, SPAs are a pleasure to work with and a pleasure to use. 1. Having to maintain and upgrade SPA type frameworks is hell and you have to do that sometimes (think Angular upgrade hell). Can't afford to start again every 5 years.
That is true. But that is also true for the backend frameworks too. All major upgrades introduce breaking changes. That's not SPA specific. And a properly written SPA (or any other application) is very upgradable. 2. The performance, and the article actually states it, is shitty at the best of times. All it takes is one client running mandatory IE11 on Citrix and you lose a customer.
Absolutely not. When done right, the performance is on-par with a regular backend-framework-served website. 3. Most of the complexity is hard complexity that has to be there to process rules. Rules are way more complex than you want to run on a client in some cases.
This is too ambiguous to comment on. Butter is buttery? 4. They are incredibly difficult to test. Go try testing a big SPA with selenium for example.
Absolutely not true. They are a blast to test. Once again, when done right. 5. Security boundaries are terribly difficult to enforce when half of your application isn't inside your control. Having done desktop development for a number of years, the worst turds I've seen are in that space and the SPA brings them all to the web which is one of the most hacked up evolutionary disasters we have ever created.
Really our responsibility as engineers, architects, developers is to give the user the best experience and that means the fastest and most reliable one. SPAs are neither. KISS is a mentality we should be using and I can build a better user experience without SPAs.
That is your opinion. You can build a better user experience without SPAs, I can build a better user experience with SPAs. Who's right then?The comments you wrote are applicable to ANY application (not just SPAs) when it's not done right. But it looks like it's somewhat of a trend here to blame everything on badly developed SPAs.
They also have the same sort of problems that Flash used to have. And there, too, you can say, that it was possible to write better apps in flash than the best you can write in HTML. It really was. There were a few really nice examples.
But ... it wasn't happening. Vast majority of flash apps sucked beyond belief. Same is true for SPAs.
> Absolutely not. When done right, the performance is on-par with a regular backend-framework-served website.
Nope. It very much is not. Because an SPA doesn't start working until it's done 5-10 server round trips, the slowest part of any website interaction. Regular-backend-framework-served websites are functional after 1 server round trip.
This is the big problem I have with SPA developers. In order to save on server round trips you make more of them. Logic at the client side. That's the theory. But they actually need more roundtrips in almost all cases, and many more during startup. So they start slower, they run slower.
So I have 2 very big problems with SPAs:
1) the "flash problem": the website owners have "more control". And they invariably use it to create heavy, slow "beautiful" monstrosities that border on unusable.
2) even if written well, they are a lot slower. First at startup, and also once running. Server round trip are the overriding cost and SPAs actually do more of them. The actual amount of data in a request, as long as it's less than, say 20kb or so, doesn't actually matter.
Incorrect. A server-side-rendered SPA will be just as functional as the regular-backend-framework-served website, that is functional after 1 server round trip, as in the html is served to the client.
This is the big problem with people who don't know how SPAs should be done. And you keep on circling the problems that should be blamed on poorly written applications and bad design choices, not SPAs as a paradigm.
The rest of your arguments seems to be based on the fact that you do not know how properly written SPAs are supposed to function, ergo the rest of your arguments is invalid, sorry.
Request Reply
(maybe some images come next, but the site is functional. Ie. showing actual useful data, also images, css, ... are simply common between both app types. Both can be inlined if you want to avoid the cost)
SPA: html reply
request javascript reply
request javascript dependencies reply
request the actual useful data the site intends to show reply
(note that these requests NEED to happen even when cached, also SPAs are of course less cacheable than server rendering)
That's 4x slower minimum. In practice, unless you implement pipelining in your api (ie. fat chance) the request javascript dependencies and request useful data steps really have to happen 5x or 10x. This will turn what is already a disaster into a global catastrophe.
Also it doesn't matter what the best developers do, for the reputation of actual types of apps. It matters what the average (ie. very bad) developers do.
There is also the added irony of discussing this article on a site that follow the exact opposite of what the article says is the one true solution for the future of web development.
Yeah, that plus actual reasoned arguments that go into detail to make their point.
The kicking point for server side is that the need for client side interaction is overblown. If you are building a tool that people will keep open for hours, by all means...SPA your heart out.
If you are building an open-check-close experience like most of the web, SPAs created more problems than they solve.
On the contrary, it's improved by not being an SPA. When I'm browsing a repository, I cmd-click new tabs out all the time, and I also copy/paste links to individual files as of specific commits to coworkers fairly regularly. All of that kind of stuff is very useful UI that you basically get for free with a decent multi-page app. It gets a lot trickier to get right with an SPA. (I'm not actually sure I've ever seen someone pull it off.)
- Templating language is basically string interpolation which builds the presentational layer at load time.
First of all, what is load time? There is compile time and runtime and then there is runtime on the server and runtime on the client. Load time is just fuzzy language and has no meaning IMHO. Also, what the blimming heck does he mean by string interpolation? Most server side templating engines are compiled, rarely string concatenated and even if that was true, how is that different on the client side? If JavaScript code dynamically creates HTML markup then it also (at some level) stitches string together or does it not?
> Client side code is developed separately and has to “pick up” the target elements after it is loaded.
Huge news announcements! The client side code has to "PICK UP" the response which the server sends to the client! OMG!!! Thank god in a SPA the client code doesn't have to "pick up" server side generated objects, right? (NOT)
> Templating languages are basically smart string interpolators and have quirky syntax.
Quirky syntax? First of all, pick an engine which isn't quirky if that's your problem, and secondly EVERY templating engine, regardless of server/client side has a "quirky syntax" if you wish. It's not like front end development is done without a framework or library which gives you more power than just rudimental HTML markup.
> One language (server side) is generating markup for a different language which takes over on the client.
One language generates output of another language is his problem? So I guess he doesn't use anything but pure JavaScript, because anything on top of pure JavaScript is another language generating JavaScript, right? Also the "server somehow takes over on the client"? What does that even mean, seriously?
> If AJAX is used to dynamically alter the state of our app by means of adding, ...
How did he transition from C# + Razor to AJAX. Did I miss something? Razor is not AJAX...
> Taking paradigms that work well for static documents and using them for building software is simply inadequate.
OMFG. client-server communication is not a paradigm for static documents. PDF is static documents.
Honestly... I stop at this point.. I can't read anymore. It's painful.
> First of all, what is load time? Load time is when server is generating HTML for request. I should have been more precise.
> Most server side templating engines are compiled, rarely string concatenated and even if that was true, how is that different on the client side? If JavaScript code dynamically creates HTML markup then it also (at some level) stitches string together or does it not
Templating languages generate string that is returned through an endpoint. Just because it is string interpolation doesn't mean it cannot have loops.
Also, by using the phrase "string interpolation" I am actually pointing out the discrepancy between the generator and the generated.
> Huge news announcements! The client side code has to "PICK UP" the response which the server sends to the client! OMG!!! Thank god in a SPA the client code doesn't have to "pick up" server side generated objects, right? (NOT)
It is not response, you have to give unique id's or smart class names and then find those elements using document.getElementById and attach to it. Having a SPA helps reduce the number of named things.
> OMFG. client-server communication is not a paradigm for static documents. PDF is static documents.
It's not a paradigm, but client asking server for a response is more suited for documents when you are returning HTML.
Agreed. It's my biggest gripe with traditional server-side rendered apps versus SPAs.
But for almost everything less than that, and that probably covers the majority of use cases, you'll have a few dynamic elements on the page, and it's just a matter of ReactDOM.render() + document.getElementById() for the handful of those.
well most spa's building the dom directly, so actually it is really a little bit different.
but yeah, I would prefer c# razor pages over any spa and I actually coded a lot with angular. however I wouldn't say that I will never touch spa stuff, but I wouldn't go full spa anymore, more like add widgets with vuejs and reactjs where it matters.
I am still not clear if the intention was to criticise:
1. The original article which was referred at the top
2. Criticise server side templating engines (but he didn't explain how a templating engine is different on the client)
3. MPA in general
4. AJAX (mentioned several times in connection with server side templating)
5. Anything which is not component based (since this is the final point in his conclusion)
6. A combination of those
Which one was it according to your understanding (genuine question)?
Thymeleaf and ERB are a lot more than "just string interpolation". Thymeleaf even uses valid xml attributes so it's not a completely different language.
My pages load and paint fast. Most pages don't need all that interactivity. In most projects I have 1 or 2 pages that are interaction-heavy and for those I usually shell out to Vue, and have my server-side templating inject the source JSON in the <script> tag so an extra request for fetching the data is not necessary.
Like Haley Joel Osment, it never got anywhere after the initial hoopla.
However no one sells training, fads, marketing, conferences, buyouts, ideologies or frameworks based around it though so there's not a lot of fanfare.
I get that some tools work better when written as SPAs, but most stuff, like my bank, news sites, most stuff really, is better without it IMO/IME.
> Modern websites can prefetch all possible links on the current page you're seeing.
I'm not sure I actually want that to happen.
> Then when you click on any link will render that page instantly. Check out some Gatsby blog generator, it's so fast.
Most of the time I visit a single page on any given blog, usually found via Google. If I have to load any JS at all the chances are I've downloaded more code than I needed. If the content requires downloading a framework before viewing the content then it just adds to the frustration.
It's totally possible to serve HTML, some styles, and some feature-enhancing javscript /fast enough/, and my experience of the evolution of Javascript on web pages over the last 18 years has led to the opinion that Javascript has steadily made my experience of the web slower, more CPU intensive (my CPU fans being spun up by someone's attempt at improving the UI of a web page isn't appreciated), less reliable, less predictable and in general, worse.
There is the very real possibility that if you write and release a Javascript based web page then I will enjoy it less than if it was something "simpler".
I recently threw together a small blog engine and wouldn't even have thought of writing it as an SPA... there was no point. Then again, a blog is mostly static document service, so it shouldn't be a surprise that picking a document service architecture made sense.
For me at least, some of the specific reasons to pick an SPA might be this:
* I'd like my user to be able to make change to a document without disrupting where they've scrolled in the document.
* It's possible to build retry logic into the SPA to get a bit of offline capability if the network connection isn't great.
* There's a block of data on a page that takes an unmanageably long time to render and I'm okay with it showing up after the body of the page.
* There's a large volume of data that can be maintained and incrementally updated within the client, rather than reload every time.
* There's a need to automatically stream and update the page in real time (and meta refresh, etc. won't work.)
* The developers assigned to the project are more comfortable with SPA and associated tooling.
* There is a high likelihood of one of the above becoming true soon enough that we wouldn't be able to rewrite to an SPA to accommodate the requirement when it arises.
Not exhaustive, but a big list anyway.... so there are often good reasons to select an SPA design. But not always. As engineers/architects, we have to do the work of understanding the requirements and planning our design..
I don't want to imply you were suggesting this, but it bears mentioning that a lot of the SPA vs MPA debate rests on a false dichotomy, where "MPA" is taken to imply that you're partying like it's 1999.
Actually, I kinda was.
Maybe a better way to put it is that I'm looking for more fluency of control in where the application code actually runs. I'm less interested in having 'an SPA' or 'an MPA' and more interested in tooling that makes it possible to more easily select between SPA and MPA characteristics for various parts of a given UI.
Edit: to make this a bit more real, here's a few thoughts on what that might look like:
* Same language on both client and server.
* Same templating on both client and server.
* Some sort of lightweight RPC-style mechanism for exposing server functionality up to the client. (Without a fully specified protocol/format/etc.)
* Framework provides an endpoint that serves up a JavaScript projection/transpile of some subset of the overall application code.
* Same thing for CSS.
* The usual automatic reload/refresh-on-change logic you get with modern client stacks.
* Setup is essentially 'add a plugin or maybe two to the project build script'.
> Templating languages are basically smart string interpolators and have quirky syntax.
Well, yes, templating languages take a string + data and return another string. That's definitely true. What that actually means isn't clear. Especially when the followup "have a quirky syntax" doesn't have a particularly precise meaning (and may not be universally true) and also, the problem remains the same whether you address it on the server or in the client.
> We cannot use server side rendering any more — or can we? Let’s write endpoints that return HTML and not JSON.
I can't tell if that last part is sarcasm, or attempt to examine a potential avenue, or a complaint that one would have to multiply endpoints in order to return JSON or HTML instead of having a back-end that pays attention to the HTTP Accept header and has capabilities of returning different representations of the same resource.
> When to subscribe/unsubscribe from events. Otherwise we will run into memory leaks.
This is also hard to decipher -- is he talking about event listeners on replaced portions of a document?
> How to name things — when everything is dynamic, naming becomes hard.
As the saying goes, naming is one of the two hard problems in software. The browser is itself a dynamic environment with a dynamic primary runtime. There are languages that'll help or hobble you in the browser or on the server but that's orthogonal to whether you're choosing an SPA.
There might be a kernel of a worthwhile argument in here about component testing and isolation being more difficult if you're doing it on both the server and the client, but the rest of this seems thinly justified rather than reasonably explored.
This strikes me as a non-issue if you still use React or the like for the dynamic elements of your page. Furthermore, if anything, having full refreshes makes the problem of memory leaks less of an issue!
My last job was like this, my current job is more of a SPA but mostly because it needs to be, because of what it is. I always thing "horses for courses" when people make opinionated statements about what tech you should use.
1) Request handling until you have a functional app in, say PHP:
GET Reply (page displays at this point)
So: 1 RT happens.
2) In an SPA
GET the html reply
Get the javascript reply
Get javascript dependencies (usually multiple) replies
Get the data to display (again usually multiple requests, because nobody does the call combining you should do (ie. don't have GetUserData(), GetFrontpageItems(), GetMessages(). Instead have GetAllStartupStuff() that returns all 3, to avoid the extra roundtrips) reply
So: 4 RT Minimum
Guess which is the overriding cost in any webapp ?
Yep, the roundtrip.
Guess why we do this SPA thing ?
Why, we do it because it's faster, of course ! (this is so ridiculous it's sad)
While I'm not the biggest fan of JS or TS, I can tell you it's much easier to develop your entire application in JS if you need to do any server side rendering. Otherwise you need to maintain two codebases that do the same thing in slightly different ways.
Regarding the article, it feels like author is angry that someone prefers server-side approach instead of his favourite way of developing apps. I disagree with a bunch of arguments in the article:
> (about server-side templates) For any large application (by large I mean more than 50 individually developed screens) this slowly becomes harder to maintain.
50 server-side templates vs 50 stateful components, I really don't see why the former is harder to maintain
> (about server-side templates) How to name things — when everything is dynamic, naming becomes hard.
Again, no idea why naming would be easier with SPAs
> Use runtime templating after AJAX call is done. We cannot use server side rendering any more — or can we? Let’s write endpoints that return HTML and not JSON.
Or course we can do that, why not? Even more - when lazily loading templates in component framework like Angular, I need to not only download the template that's in HTML, but also Angular needs to compile that template.
> Let’s be honest — the only way one can say developing SPA application is costly is if they either don’t know any SPA technology or if they don’t want to learn it.
I don't have any hard data, but neither does the author, so I guess we'll focus on personal experience. From my experience keeping state only in the backend is easier to maintain and therefore cheaper than keeping the state both in the backend and in the frontend.
> Knowing server side templating language. Also not being able to use the same language for AJAX templating.
But to write client components I also need to learn some Angular templating syntax or JSX or some other stuff. And it's not simpler to learn than let's say PHP templating.
If I use PHP for my backend, then I don't need to learn template language, because I just use HTML + embedded PHP.
> If you have proper mobile app, an API has to be developed for that. Having two layers accessing the same data in two different ways is not practical.
That's a fair point, however it doesn't make a big difference. Using SPA I need to develop JSON API + mobile views + SPA components Using multi page app, I need to develop JSON API + mobile views + server side templates
> State on the client — because that is where the state belongs to.
But why? The state does not need to belong to the client. The client might be a representation of the state that comes from the server.