Server-side rendering is a better choice for many applications (2020)
timr.co
timr.co
function vote (id, how, auth, _goto) {
...
$('unv_' + id).innerHTML = unv;
new Image().src = vurl(id, how, auth, _goto);
}Information-theoretic, there is no way you can beat SSR in this scenario. You will not win against a machine that returns a complete HTML document on the very first request if your users only receive hints regarding where to actually find the princess upon their first request.
I look at every client-side argument along the axis of "well now that the universe is already here, we can get started". Server-side explains how that universe got into existence in the first place. Your fancy incremental update shadow DOM system cannot work until it is already bootstrapped via some means.
I think this is generally true, but it does depend on how long it takes SSR to complete. If that's slow, you could potentially be faster by sending a bit of JS+HTML and allowing processing to continue in the background to be fetched later when it's ready instead of waiting for everything.
That said, I think that's a fairly unrealistic scenario since a bad connection with high latency is probably more of an overhead.
SSR that needs to run JavaScript hydration needs to download more content (the html and js bundle) than a spa before it’s interactive.
I don’t know why the community collectively decided that first-contentful-paint is a more important metric than time-to-interactive. Seeing a page quickly and waiting a noticeable amount of time for it be functional seems like the worst possible ux, especially when there is no signal to the user when the JS has loaded.
This is not SSR.
If you do SSR, the client is much more limited in terms of caching because the page contents is not constant. In my opinion, SSR is actually more for slow CPUs than for slow networks since you can make the network usage for client side rendering very efficient as well, but client side rendering will always be worse in terms of client CPU.
For me this is 45ms to transfer the 2 kB (compressed) of HTML; the whole process takes under 60ms total, which is pretty darn close to "instantaneous" for the "complete page reload."
EDIT: I'm in Texas, so most of this time is probably just round trip time to the west coast.
It's about 120 ms here (wifi off of gigabit fiber, east coast US.) Based on ping time, over 60% of that time is network latency to the west coast. Actual "processing" would be in the 50 ms range which is super fast.
In the context of the comment to which you're replying[0] I'm not sure how else to take your comment. OK, you don't like HN's UX, that's either a comment on SSR and on topic for the thread, or completely unrelated.
> HN as a site is a perfect example of how bad a SSR experience can be.
This is a great ending line if the things you list before it would automatically be better under CSR, or are only capable of being fixed by moving HN to CSR. So, it seems pretty natural to me to assume that you're saying those things (reply notifications, typography, losing position on a reply) would be better under CSR, which is not necessarily the case.
No, hacker news is not a static site. It just makes use of caching HTML on unchanged pages, and as I understand it that cache is often bypassed for logged in users. This is why sometimes when hackernews is overloaded you can still view the site in private browsing, since you're not logged in it hits the cache instead of generating a page for you.
A cache is not a static site, although maybe next.js is redefining the term, I don't know. Get off my lawn.
What I actually mean is, that there is a difference between SSR with react, which requires some kind of rehydration on the client, in contrast to a website generated by, e.g., PHP on the server, which doesn't require this.
The PHP website doesn't require the client to rehydrate and produces less load on the client. With the disadvantage, that a subsequent page view requires again a full load, while the SSR loaded react page, doesn't require that.
I didn't check the HN code yet, but it feels like a server- side generated website and not a SSR delivered react (or similar js framework) website...
Here's a simple way to think about it.
SSG: there will be a process that generates/bundles HTML/CSS/JS ahead of time with all of the content that the site will have, like the many static site generators out there.
You should then be able to take the output of the SSG process and host it on a dumb web server, like Apache/Nginx.
For example, that's what I do with my HN Personal Blogs site, a set of Python scripts generate HTML output a few times per day, which is then served on an Apache container: https://hn-blogs.kronis.dev/
SSR: there will be a runtime of some sort that will execute any number of scripts on the server, to dynamically generate a response for the user's request.
This is what many PHP and Ruby sites are, if they don't opt to just use those languages for an API. You click on a button in the site, your request is submitted, the language runs some logic on the server and sends you a response, typically there's a DB as well, that most users interact with.
However, you can also mix those approaches. For example, you could make it so that the front page of your site is pre-rendered or at least cached, so that your servers need to do less processing and your DB would be under less load.
That's also what some flat file CMSes like Grav do - so that the articles will load pretty quickly, though those approaches introduce some complexity and the risk of stale data in some cases.
There's also stuff like hydration and many more recent concepts, but that'd get more lengthy.
I don't think CSR is going anywhere, mainly thanks to Conway's Law.
If anything, I'd say that with server rendering, separating different modules is easier. You want to rewrite that page? No problems. With client-side rendering there's usually expectation of some monolith project using the single framework.
1. Written in different languages.
2. Completely different deployment paths.
3. Causing completely different ways of scaling.
4. Focus on UI and UX is a very different mindset, with often some people preferring it to be a focus of their work, or not.
It also gets you vastly more choice in language/tooling/etc, even allowing a mixture of different ones, which is what attracts me to SSR. Of course this may change in the future once WebAssembly has had most of the DOM interop overhead optimized away, bringing this freedom to CSR.
The very first step in creating this separation is to define an API that is implemented and operated by backend devs and used by frontend devs. Once you have done that, you have achieved all the clarity that is necessary or possible.
Whether or not some parts of the frontend are executed on the server-side shouldn't matter for the question of who has responsibility for what.
Perhaps it's more about the ease of hiring for different skillsets. If frontend is synonymous with client-side and backend is synonymous with server-side, it makes life easier for HR and recruiters.
I love the 'CHAMP' stack, which stands for CSS, HTML, Apache, MySQL and PHP. ;) Clear separation between frontend and backend.
I'm almost happy that I started webdev in the 90's. This 'ancient' technology is still going strong, with websites and a whole lot of webapps.
Specifically, it depends on context. How big is the app? How many people are involved in building it?
As with many things, separation of front and back ends grew out of web-scale companies and products. If you're buiding Facebook or Spotify or Gmail, then you need a way to partition your app - because you need to partition your people. Humans need structure, we don't deal well with single teams of multiple hundreds.
Many apps don't fit that model. Lots of apps - e.g. business internal apps - might target at most small 100s of users and justify a dev team of < 10. In that world, separation of front end and back end devs & stacks is a disadvantage. Single language, single build apps mean less technical surface for the team to cover. Which means each person can more flexibly turn their hand to the requirements. Most people can do most things end to end. Features are business-driven and end to end. A single PR can deliver a meaningful piece of user-accessible value. There's no unionised demarcation.
None of which says "separate UI & back end is universally wrong". But it's not universally right either. As is so often the case, it degenerates into a discussion that is technical and absolute when the underlying forces are organisational and relative.
You say this as if it is necessarily good, but I disagree and would even say it's actually a hindrance for many teams. It often adds inefficiences, increases costs and makes planning and collaboration more difficult.
> the fact that you get an API by default with CSR is also nice
The vast majority of applications don't need an API.
Yes, and if a single team is doing both it adds another stack to master. This can be a pro or con depending on the size/organization of the team.
Seems like answering with SSR would fail a Thiel interview for two reasons:
1. It's not important (in the grand scheme of things)
2. It's not a view that very few people hold. SSR was the standard way to do things for a couple of decades up until frameworks like React, and React itself now implements SSR, doesn't it?
Thiel uses this question to try and determine if someone is or can be a free thinker, someone who can discern something to be true even in the face of significant social opposition. That's valuable if you're an investor looking for overlooked opportunities, or an entrepreneur trying to find an edge in a highly competitive market. But there is no taboo or significant social opposition to SSR webapps, and bluntly, no edge to be found there.
> 2. It's not a view that very few people hold.
And yet it makes the author feel a contrarian free thinker. It turns out, it's the prototypical Thiel truth!
There's no attack surface here at all, the only issue with most client-side apps and interaction with server comes from CORS and devs copypasting solutions from SO to get rid of the warning, thus creating the attack surface.
The choices related to displaying appropriate elements based on current user's role that's tied to entire logic of the app has literally zero to do with security.
No, the whole point of client-side rendering is to apply parasitic computing and offload the server by having the client perform work it can thus saving the bandwith and compute power.
Next benefit is application that's "snappy" and works well, which is what almost never happens sadly.
> that’s why you have JWTs and stuff like that.
No, you don't have JWT and "stuff like that" because of this. JWT is for offloading databases so you don't have to talk to a DB on every request since you can verify the token via signature check and thus implement distributed services that don't have to talk to central authority to authorize a request.
> where state is able to be maintained per user usually up by the same thread on the same physical server
And now you're trying to sound smart by adding servers and "threads". I've a feeling you're pulling my leg right now so I'll excuse myself since you started spouting absolute nonsense.
Concerning JWT, I think we were talking past each other as I was referring to a session-less Authentication scheme, which is more or less what you describe.
Finally, there’s no reason why the server can’t render JavaScript as well other parts of the page. In effect, if the server wanted to, it could render of a reactive version or an angular version depending on a variable. Can the client do that?
You have to be sure your data going into the database doesn't have XSS escapes or your rendering of untrustworthy data doesn't have such XSS escapes.
Which is why you shouldn't roll your own SSR unless you are fully aware of this.
SPA doesn't have this problem as it will generally insert DB data into the DOM as text, no possibility of escape or execution by potentially malicious database entries. Not that you can't have issues in an SPA, but you have to do work to bring them about.
If I get a user-provided string from the server as a JSON property and set it via `.innerHTML =`, I have an XSS vulnerability. If I use React's JSX string interpolation, I don't.
If I get a user-provided string from a database and inject it with a PHP `<?= ?>` tag directly, I have an XSS vulnerability. If I use Laravel with Blade templates [0], I don't.
You're not saved from XSS by virtue of using JavaScript to render your code, you're saved from XSS by using a framework that escapes everything by default. Whether that framework builds the escaped HTML on the client or the server is immaterial.
Everything rendered by the server has this potential as it must be deserialized by the browser.
No, but I've definitely seen bespoke, hand-rolled frontend code do it. You can't select SPA frameworks as representative of frontend rendering but look only at hand-rolled PHP from 2002 for backend rendering.
No major SSR framework is XSS-vulnerable by default. Whether you're using Rails, Laravel, Spring, ASP.NET, Phoenix, or whatever, every template engine escapes your strings unless you opt-in with something like Rails's `html_safe`, and they have for over a decade. Unless you've built your own SSR framework by hand with raw string interpolation, the "easy" way to do things is also the right way, just as it is in React.
Yes, congratulations, you pointed out that you can hang yourself either way. That wasn't my point and I acknowledged as much in the first post.
One has an unsanitized escape free method and the other does not.
As for speed concerns, server rendering is almost never the bottleneck for any application. DOM rendering can be slow, but even JS renders several magnitudes faster than any network action. So your latency to the server alone is always going to be much, much slower than your render. Same with any network calls your app has to make, DB access, etc. In my many years of building SSR apps I have never had to optimize a render.
I’m looking at you, JSX. >_>
I disagree with this premise.
Dynamic languages don't have builds either.
You had me until the last part which seems to contradict everything you said beforehand as you now have to test everything being rendered server-side. Why render it server-side if it's already in JS and capable of being rendered on the client? Optimize your bundles if you're chasing lighthouse scores.
I use vanilla html/css/js for frontend + golang for the backend. Modern JS (esp. modules) are very powerful. ESLint provides pretty good static checks for the frontend, and of course golang is statically typed so you get strong guarantees about your backend. Go builds extremely fast as a small self contained binary that can run on any OS and in a from scratch docker container. Go performance and tooling blows JS out of the water. And go has a powerful built-in templating engine for SSR which allows to to make your JS even leaner. Testing a change requires no more than refreshing the page. Debugging is super easy, barely an inconvenience since there are no build layers between anything encumbering developer velocity. Just add breakpoints directly to chrome devtools in the JS (or in VSCode for the golang) and step through.
Always start vanilla. Most of the time you won't need to be dependent on npm, you'll never break when some random maintainer becomes an activist, people will wonder why your site page loads are so snappy, and you'll live happily ever after.
It's messy and you end up writing helper functions for pretty much everything. Need a href aware navbar? Custom function and macro time. Bleh.
Performance is great, maintainability isn't.
I dislike graphql because it's too mich overhead. RESTful is not good enough, only good for admin UI CRUD.
I moved to json rpc calls. So I can have the best of both worlds.
However what I'd really like to have is a proper SSR component framework that is interactive or rather reactive.
I want my cake and eat it too.
For Go, unless I missed some new development, there's Kyoto and jfyne/live . And that's it for Go.
Kyoto IMHO is more of a poc. And live is not very appealing, you're back in complicated camp with it.
Don’t get me wrong, I’m very unhappy with the state of today’s JS ecosystem but if you’re building a project of any complexity ditching absolutely everything that can help you along the way is not going to work out. Nor is it going to work out for the person taking over the code from you.
Every now and then I’ll be putting together a tiny landing page type thing and write it all in vanilla JS and it’s bliss. But as soon as I start dealing with non-trivial state you’d better believe I’m reaching for a framework.
Browsers natively support JS modules with no frontend builds needed (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guid...).
You just need to specify `type="module"` in your `<script>` tag
And yet, SQLite does just that. They distribute as a single .c file. I wrote a moderately successful lcov replacement in python that I distribute as a single .py file so people can directly run it without needing pip (if desired). There's a time and a place for needing build systems, but as a minimalist I default to vanilla + no build system and that serves me very well the vast majority of the time.
> and you shouldn't distribute or deploy a frontend application without the equivalent dependency management and build orchestration
Why not? That's the other thing. What are all these dependencies you are talking about that need "managing"? Most web apps I've written have needed 1 dependency (bootstrap CSS). Maybe PIXI or ThreeJS if making something graphical. Include it in the html, boom done, no npm needed.
Take a look at this guy's blog and tell me that he needs to abandon vanilla and start using a frontend build system: https://ciechanow.ski/gps/
I don't know your background but most teams don't view "single language" as an advantage over other options. People choose a certain language because of internal infrastructure, libraries/ecosystem, performance, and whether it is the best suited for a project etc, rarely because "we use that language for backend so we should also use it for frontend" or vice versa
We view it as a massive advantage, assuming we are on the same page with "single language, plus HTML/CSS/JS"
Our language is C#. Our web "framework" consists of the string interpolation and verbatim operators. Most of our views take the form of:
var finalHtmlResponse = @$"
<html>
{DiyPHPViewEngineRabbitHoleEntrance(httpRequestContext)}
</html>";
I actually tried using the cshtml/razor engines because it seemed "more proper" but after 2 days of dependency hell I decided to go back to raw string interpolation. If you are able to build a functional website using static sources and have the barest capability to compose functions and strings, I do not see why this path would provoke any serious anxiety (other than it not being popular).Imagine being able to directly invoke some utility or other backend method from your HTML view source pipeline. If you write it all in the same language, this becomes feasible. The moment principal rendering is outsourced to the client (or some other language), you are talking about a JSON API + distributed state circus and all the hell that must go along with it.
Either way, at some point your app is running JS/TS and CSS, and those two resources require some type of build process to manage beyond a certain degree of complexity. I lived through the hell of having to determine the load order of JS and CSS files by where the script and style tags occurred in the DOM. It was incredibly difficult to do simple things. Now we can do much more complicated things more easily, but language chauvinists object to doing complex things in what they view as "lightweight" languages. The thing is, the "correct" language to use is generally just the one that does the job best, and in this case JS/TS is specifically optimized for writing applications that interface with the DOM.
Sane dependency management is NuGet, not NPM. Sane build tooling is dotnet build, not npm run build (is this multithreaded/parallel yet?). Sane CI is achieved via dotnet package; then chucked into whatever CI workflow.
It just works. You don’t need to mess with it. It adds negligible overhead.
The DOM is inefficient — entire page loads are quicker than rendering changes in-page (accounting for latency, and using chromium’s Blink renderer). The box model is inane. JS is a horrible, cobbled together language (like Python) initially designed by a naive. I would sooner write my own 2D renderer in WebGL than deal with HTML/CSS/JS/Rendering pipelines.
In my many years of being a web$hit, I have always had to fight the frontend ecosystem to stop being daft.
2. CSS has NOTHING to do with js/ts.
3. Most single page js applications require SSR anyway, otherwise you have a blank screen or spinner until the browser has downloaded & intialized everything.
Personally, i dont care if it's SSR or SPA. But the js/ts community tends to use things like webpack in combination with ~20 packages which themselfs rely on ~20 packages, resulting in index.js files that are +2MB... That's bad programming.
If you have a frontend app that requires loading a 2MB bundle in the browser, then whoever configured that application did not know what they are doing. There are lots of ways of optimizing JS bundle sizes, and SSR is actually one of the best. With SSR, only the code that executes on the frontend gets included in the client bundle. Webpack is one of many build orchestration frameworks you could use, though honestly at this point you rarely have to actually write custom configuration for frontend applications. A great deal of standardization has happened over the last 5 years, and generally you just use a template for your use case.
As someone who has worked all over the stack, from API development to data pipelines to infrastructure to client-facing application, I find the dismissive attitude of other parts of the stack incredibly bizarre. It's a tool, it exists for a reason, and if you don't see the reason it's probably because you don't understand the problem.
> I agree/disagree with the article's premise because of this thing I absolutely know is true.
> You are totally wrong.
It is one thing to push an abstract policy/principle. It is another to hand someone a live, working implementation of a policy and request that they keep moving down the indicated path.
I don't think SSR is a Thiel Truth. I think leadership is. If you want to see more SSR in the world around you, you have to build more SSR experiences and teams around them.
Letting a room full of arbitrary developers sit around a conf call and come up with "the tech stack" is how you wind up in a hurricane of bullshit most of the time. At some point someone needs to ask the question "are we here to make money or have fun?" which should quickly highlight your ideal candidates for CTO/dictator.
Large structural changes can often then be made early in the project by a single person or alternate concepts quickly prototyped when it's effectively a monolith -- you don't as quickly get locked into "we'll just have to live with that now"
I'm not against introducing client-side once the final functional form is reached if justifiable gains somewhere -- but from day-one it's usually just a headwind on a project of any complexity
> You will need a backend anyway. It'll need to expose data to users. Exposing it as HTML is no harder than doing it via JSON or GraphQL
Sure, if your "app" is just buttons and UI that interacts with a backend DB, I agree. However, many PWAs and native apps do lots of heavy lifting on the client side, and loading the backend with that is not cheap at all!
even more, many backends can be simple CRUD. i reuse my backend for all websites and haven't had to do any custom backend coding in years. so my current backend cost is zero, because i can do it all in the frontend.
Ads causing reflow, embedding of other elements (off-site) with poor performance, the Cambrian explosion of trackers and other cancerous marketing-related cruft, labyrinthine page layouts because someone wanted a pixel-perfect visual. All things which are not the core app itself. This leads me to suspect that most apps would work just fine with a few easily anticipated exceptions.
It's called truth, period, never mind that pillock. There is enough cult of personality in SV already.
So has it taken off / is it taking off? If not, why not? Or more to the point of my original comment: Why is something like this just now taking off? Has something new enabled this in the last few years?
It's not a new idea was my point in my comment, so I'm curious why the idea never seemed to take off in the past, and why it might be poised to now.
I don't know enough about any of the frameworks you mentioned to evaluate whether the "hybrid in some capacity" actually does mean this approach has become widely used, but I guess from my experience of using the web, it doesn't seem like it is common, it seems like most applications are still sending a skeleton and then filling the data in client-side, rather than rendering the initial page load server-side.
My experience is that most of the time it’s better to make your public facing site fully SSR and then make the actual app fully client side rendered. You usually don’t need that much interactivity for your public site and your app users don’t mind a few seconds startup time. You also usually don’t need SEO for your app because it’s behind authentication anyway.
Exceptions exist of course.
Those are basically the same drawbacks as a decade ago.
I guess my question to the folks here saying hybrid is the way to go nowadays is: Have these problems been solved in your view?
I hope by app you mean "webapp", because I sure don't want all my apps becoming websites. That's how Electron becomes more prevalent.
Also, great to see a shout-out to D :)
I really think this should be the first question on a project: Should this be a website or an application? I think the answer to a huge number of technical questions is dependent on the answer to this product question. And it seems like too few people are asking it, and are instead diving straight into making an application (whether web and native).
Modern architecture fashion tells us that we need to use micro services. So even if I generate markup on the server, I need to talk to micro services using HTTP to get data.
So the question is: which technology provides best tools for writing server-side rendering module?
My wishes:
1. Strict-typed language. 2. Compiler-checked HTML output. 3. Flexible CSS output.
So one should be able to write reusable components and easily write required markup.
IMO best tool nowadays is TypeScript + React.
I can only hope that this is satire
Haskell can do that.
So what I'm saying is there's a reason people ran to client side rendering and blindly running the other way for the sake of being a contrarian is equally silly.
SvelteKit, in my opinion, did a fantastic job implementing the best of both server-side rendering and client-side hydration and navigation by default (with any amount of route-level mixing and matching you want to do). I was skeptical of client-side navigation in particular, but it really does make my app feel so much snappier.
But even google earth would be better as a desktop application.
"Title: A Stalin-inspired Look at Webfarm Management
Body: Apocryphally, Stalin once said that quantity has a quality all its own. As such, our hosting system involves an absolutely bonkers number of servers."
> Client-side apps are wads of Javascript that must be loaded and parsed before it can load and parse JSON which it can then transformed into HTML. Precisely nothing about this is optimal for browsers and networks. Many applications are used infrequently and browser caches are not magic (and disagree with you about how important you app is), therefore arguing 'each user only has to load it once' is bullshit.
The "wads of Javascript" is optional. The "must be loaded and parsed" can be trivial, and js is fast, so the "load and parse JSON ... into HTML" is FUD. As for the infrequency of app use, CDNs cache and deliver app source fast.
I'd like to see some actual numbers of the best-case Client-side apps and critique that, say maybe Svelte. Perhaps this post was somewhat relevant in 2020.
> Unless your app is something used frequently and for a decent period, with lots of low-latency interaction (forms do not count: think editing, iterating), it will certainly be faster server-side rendered.
Then it goes on to talk about mobile apps--I never considered this to be an either/or.
The biggest gains of SSR was SEO. I'm not a webdev, last I recall a hybrid SSR for first load, then Client-side app for rest is state-of-the-art.
That aside, just use whatever fits best for the task at hand. If server-side rendering works better for you, use that. If client-side rendering is preferable, do that instead. Or a mix of the two. No need to be dogmatic about it.
It seems like a big deal to me and the entire shift is an indicator of how much the IT community is behind front end clients talking to a separate back end. Server side rendering is no longer considered normal. Server site rendering now means something entirely different. It is about running your frontend code on the back end, So you still have the separation, but instead running it on the same machine. Now the same ui code has to be compatible with two different run times. This is much, much more complex than traditional server side rendering.
I'm glad we now have things like single page apps and client site interactive applications, because some apps were really not possible with server side rendering unless with a lot of Jquery hackery that quickly becomes unmaintainable...
However, I do think that front end technologies are overused, so I agree with the author, And I also think this is objectively a contrarian opinion, considering my initial point.
And maybe server side rendering is just the right answer for websites which are not the two you mentioned.
There is an echo chamber where this happened:
* Facing massive datacenter costs, Google and Meta realized that if they could hand off rendering to the client, they could have smaller datacenters and save a lot of money. Things like React and Angular were born. Other companies with large datacenter costs followed suit, many monies were saved.
* This is when things started to get a little crazy. VCs started pushing heavy client-side SPA this and that because if anyone knows how to cargo cult, it's VCs. Devs started pushing it because it was a hard way to do things and if anything improves your salary, it's being involved with the hard bleeding edge stuff. Also inventing another JS framework turned out to be a great way to pad your resume. Design and UX people realized this was a whole new can of worms they could get paid to open, and dug right in. (In all cases note that the original point, saving money on compute at massive scale, was totally lost, and people just made up new reasons.)
* Outside of this echo chamber which is utterly convinced it's filled with the smartest people in tech, life has actually gone on pretty normally for the rest of us, we're still doing stuff on the server whenever we can, and caching the hell out of everything we can, and being judicious with fancy client side frosting because complexity is generally the enemy. That said, it's definitely true that an entire generation of young web developers has been lost to madness because young web developers also like to cargo cult a lot, and the damage will take years to repair.
But yeah, not really a Thiel truth
I can't think of anyone who doesn't want to save money on servers. Seems like a pretty good general win to me for using the client.
> complexity is generally the enemy
Agreed. But minimizing complexity doesn't require not using a heavy client. You can go fully the other way and make the backend a relatively simple permissions and validation mask on top of a database and let the front end hold all the relevant state.
Use client side rendering and have simplicity too.
I will admit that an SPA turns out to be easier to mess up and design really poorly, but I believe that this is a tooling maturity issue rather than fundamental to the platform. SSR frameworks have had over a decade longer to mature.
Reflecting, I suppose that businesses relying on Php/Laravel or Ruby are probably still enjoying simple SSR development. I've personally transitioned to Java and then .NET, and haven't seen SSR since. Which corner of software are you in, where you see SSR still being dominant?
For one thing, I don't think the motivation of Google and Meta was datacenter costs, though I could be wrong about that.
But it's not that "VCs were pushing client-side SPA", it's that lots of the companies that wanted to build applications, found that they had a set of problems that was best solved by things like Angular. The state of the art before that for highly interactive client-side apps was JQuery, and for a few years, things like Backbone.
Angular solved a real problem - people wanted to build more complex and more interactive client applications in a browser, but just using regular JS (or JS with Jquery) led to really messy applications and was very hard on development.
You can try and handwave all that away as an echochamber, but I think the majority of the industry moved to SPA frameworks as solutions for building client-side apps.
Have you forgotten that these are profit-maximizing companies? Why do you think they do anything? To maximize profits. That is always the answer. If it doesn't maximize profits it's a mistake and they will back away from it.
So for example Facebook either thought that React would increase sales, or reduce costs, otherwise they wouldn't have created it. React hasn't moved the sales needle for them (why would it - they are an advertising company - React has precious little to do with selling more advertising). Ergo it was created to reduce costs. The cost benefit of moving all that compute out to the client is easy to demonstrate and significant for a company of that size.
My own memory of the history of the web is that early web sites with a lot of client-side interactivity benefited greatly from the huge leap in interactivity, and came out several years before JavaScript libraries were widely available for ordinary developers to build web sites with similar functionality. (I'm not counting arguably "non-web" technologies like Flash and Java applets.) The earliest such web sites I can remember are e-mail, calendar, and mapping apps.
Naturally after years of investment in building consumer-facing sites like this, the skills and tools became ubiquitous and arguably overused.
Blaming frameworks seems misguided.
Using traditional Java and .NET stacks for the last 20 years.
Naturally in the context of being yet another cog on the enterprise machine, doesn't always go that way, however when given the option, Java and .NET Web stacks as always.
Sure you can get by on htmx/html/css/tailwind/whatever simplistic thing you can conjure up but those things don't SCALE, which is what these frameworks are built to do.
Who? When? Where? I refuse to believe this assertion. Are we talking past or present? The whole reason why these frontend focused frameworks exist is because either the existing solutions (pure html, even with preprocessors like handlebars, pure vanilla JS, lower level libs like jQuery) did not scale to meet demand or existing frameworks (JSP, PHP, etc) became a mess at scale.
Everyone loves to throw out these imaginary success stories of corps rolling just with html/css but I've never seen it actually proven true with evidence.
Your assertion that older frameworks 'became a mess at scale' is a sweeping generalization. Any technology can become a mess if not properly managed; that's not a failing of the technology but of the architecture and development practices. PHP, for instance, powers Wikipedia, one of the top-ten most visited websites in the world, and it handles this scale quite well.
The emergence of frontend frameworks was not solely because 'existing solutions did not scale'; it was also driven by the industry's evolving needs for richer user experiences and faster development cycles. These frameworks solve specific problems but come with their own trade-offs, including complexity and steep learning curves. To dismiss alternative approaches as unscalable without evidence is not just intellectually lazy; it's a disservice to the field of software engineering, which thrives on diverse solutions to complex problems.
If that was the case we wouldn’t have the other problem we have on the front end. A million and 1 different web frameworks.
Especially for indiemakers and startups by technical founders.
All the frameworks add so much complexity and confusion.
And I have seen several startups fail because when the developer was confronted with breaking changes of their framework, they said "Ok, that's enough. I'm not going to plow through this".
The simple "PHP or Python talks to the DB and outputs an HTML interface" type startups have a pretty good success ratio on the other hand.
You don’t want to deal with processing a raw http request from the web server. You don’t want to split headers. You don’t want to sanitize input params, deal with character encoding, content types, gzipping, cache control, etags, basic authentication, flushing headers, chunking bodies, file streaming, tcp sockets, slow client avoidance, and probably 1000 other things I can’t recall.
No matter how unnecessarily complex you think a http framework might be, I assure you, it’s saving you from a mountain of already solved by people smarter than you or I complexity.
You don’t want to deal with ...
Well, I do all that and it works just fine for me.All my projects are 100% my own code down to the core. No frameworks, nothing. There might be some traces of jquery in there from when browsers were more unreliable. I don't even use that these days.
To get to know those frameworks, I built some projects with Symfony, Laravel, Django and some others. But it didn't stick. They are too aggressive in their "do it my way, don't worry what happens behind the scenes, let me do the magic" approach. I had the best impression of Django. That is the only one I might give another try.
Huge difference between working fine, and working right. The security implications of rolling your own, is why I say “you don’t want to…”
Also, none of that code has anything to do with the product you’re actually trying to build. Imo it’s additional maintaining, tech debt, attack surface, and it’s a solved problem by a large community and has more knowledge from the security community baked in, and more eyes finding and plugging holes.
I understand why these are designed that way, but also don’t enjoy using them. Frameworks can feel very narcissistic in that sense, all the code is about them, despite their promise that you’ll focus on your domain more.
I need to play with some of the Kotlin web libraries more, such as ktor or Javalin. There has to be something better out there.
Also, even though you don't use frameworks, I assume you use various libraries to handle web requests and such, right?
When I think about heavy, I think about how hard it would be to replace the framework with my own code in the future. So I don't like magic.
One thing that keeps me from investigating Flask further is that Django seems to be way more popular:
https://trends.google.com/trends/explore?date=all&q=django%2...
So it will probably stay around longer.
Me and other devs maintain this repo which shows how to get from a fresh Debian install to a running web app via different frameworks:
https://github.com/no-gravity/web_app_from_scratch
As you can see, it also has a Flask version.
Contributions are welcome!
As for libraries: PHP has great http and html support build in already. Python is a bit tricky in this regard. That's why I would give Django another try for new web projects. But I also had success just rolling my own http/html code in Python.
Because it is, by far, much larger project? Django has 551k LoC in 31933 commits, Flask has 27k LoC in 5156 commits. Django philosophy is "be opinioated, and bundle everything necessary for developers". Flask philosophy is "do just one thing and just be a good HTTP server, let users pick a solution to all the other problems". Django is a full-blown framework, whereas flask is almost a library. Both approaches are OK, but from your previous message (GP) you prefer lightweight and magic-less frameworks (and Django relies on some conventions to do its magic).
>One thing that keeps me from investigating Flask further is that Django seems to be way more popular:
Both Django and Flask are way more popular that what you're doing (writing everyting yourself. By the way does it mean you write your own HTTP server too?), so I don't know why that stops you. Flask is not going anywhere.
>Me and other devs maintain this repo which shows how to get from a fresh Debian install to a running web app via different frameworks:
Interesting project, thanks for sharing! But that's a bit random - what was your intention when linking it? Also I can't help but notice that the flask example there has three third-party dependencies other than flask (flask-sqlalchemy, flask-login and wtforms). Since you like rolling your own solutions, maybe you would prefer Flask without such libraries? (I personally don't use flask-login and wtforms, and only sometimes use flask-sqlalchemy - I usually use standard sqlalchemy, my custom ORM, or just write SQL directly for simpler projects).
As for Flask not going anywhere - well, all projects go down the drain at some point. Just 10 years ago, the Zend framework was more popular than Django and Flask combined:
https://trends.google.com/trends/explore?date=all&q=django%2...
Good point about the dependencies of the flask version. I did not write it.
If you like to write a pull request which gets rid of the flask-sqlalchemy and replaces it with pure SQL, I would love to see that.
The Golang stdlib does all this for you, no framework needed :)
I honestly think Golang SSR with html templates + a sprinkling of Javascript to enhance is an extremely pragmatic way to go.
You build your entire service into a single binary (assets included with go:embed).
You shed the complexity of the framework AND the web server AND deployment in addition to React etc.
My own personal experience has been working at a large enterprise SSR app that ultimately failed to keep pace with increasing competition (but certainly achieved some success with basic SSR forms in the early 00s), then later worked for a team that had a $500M exit for which the CSR app and backend Node.js API was built with a minimal team size of just a few dozen devs.
I have no doubt someone will bring up levelsio (hey Peter!) and his slew of wildly successful sites SSR sites powered by JQuery and PHP, but I've always felt his stack choice was secondary to his ability to market and quickly ship.
It's a bit of a truism, but I've really come to accept these days that the best stack is whichever one your team is most productive with.
And that iteration speed is key for chasing down product market fit, which is way more dangerous to a company than suboptimal tech.
People get so intimidated by these huge frameworks and get FOMO, that they never try to build something from scratch.
React seems simple, but if you tried to understand what is going on under the hood it would take you months.
Simple should be: can you trace through all the code yourself. Like Backbone.js for example.
Plus, there is already so much rendering complexity under the hood in browser engines. The DOM and CSS are already incredible abstractions available for you to use.
I really don't get what is so bad about just having some object to manage a dom element's rendering.
Create a single relational source of truth for your data. Then create some view models that listen to this source of truth. Then make your objects listen to these view models.
This vdom diffing stuff is so overated.
If you have a list of items, and a new item is inserted, I can just insert that directly into the dom. If I render a different entity and it uses mostly the same dom elements, it's really not that hard to tell say: here are some new props, compare them with your old ones, and do what you think is best. React promises this for the entire app but its all magic. I want control of my rendering so I can make things fast. Debugging perf issues in React is insane. Good luck debugging anything.
Money has never existed without taxation
1. Store of Value 2. Unit of Account 3. Medium of Exchange
Of which it's fair to say that several crypto currencies fit that bill.
If you want to think of it as a unit of account, it has to be a state unit of account in order to actually function as money.
And finally I think that the function of money as a medium of exchange is actually a side effect; that is to say that money is the most liquid asset because it is created by an obligation in common to all citizens of a sovereign entity. As such, it is the most likely medium of exchange because it is universally accepted.
However, anything can be a medium of exchange. Hot rocks can be used to heat a room, but you wouldn't call a pile of hot rocks a heater. In the same way, virtually anything can be a medium of exchange, but money (by virtue of being created by the imposition of a tax liability) is the most effective medium of exchange.
My definition of money is: a credit that can be used to extinguish a tax liability imposed by a sovereign. Everything else is a commodity.
Fiat currencies don't have these problems[1]. Because they are instituted by a government that forces people to use it, they have a large volume of economic activity which makes it harder for the currency to swing dramatically in value. The reason why Bitcoin can fluctuate so wildly is because few actually use it like a currency, so there's nothing to buffer against market manipulators and forex speculators.
[0] Because crypto needs global consensus over every satoshi in the system, all transactions need to be widely propagated to all full nodes, which imposes strict limits on how much transaction data can be processed at once. If the limits are too high then only large institutions can run full nodes which is centralizing.
Of course, literally everything else in crypto is centralizing, because centralization is the gravitational force of economics.
[1] No, Zimbabwe doesn't count.
They're charged by the entity that issues the currency (the network/the miners), for the act of using the currency, which I think could reasonably be classified as a form of tax.
Demand for that token is thus entirely speculative and could evaporate at any time. Since there is no issuing authority that guarantees to accept the token in order to exonerate some obligation we have in common the last person holding the token simply loses the game.
Of course many boring posters on HN will never accept that because their models of the world only allow for 1 dimensional villains on the other side of any ideological disagreements.
(Mandatory HN joke explanation: https://en.wikipedia.org/wiki/Render_unto_Caesar plus a pun on the original thread title)
(i.e. he'd reject this as boringly conventional before it got to the level of does it make sense? I've only read a little bit of Thiel, like 2-3 blog posts worth.)
My favorite is when a full react site loads up, doesn’t have error boundaries, hits some unimportant js exception, and the entire page that was fully rendered and ready to go just pops out of existence and you are looking at a white page. That doesn’t seem like forward progress at all.
If a page is presented, it better be f&@king usable
People like to talk badly about w3schools but at least it manages the bear minimum of actually being able to render and display the information I’m looking for.
JavaScript is eventually needed for any non-trivial app. JS without a build system/dependency management is a maintenance nightmare. JS without linting, TypeScript, module syntax and unit tests is a maintenance nightmare.
Reuse of components is much easier and more testable with framework abstractions (compare a react/vue/svelte component to e.g. a laravel blade component).
Strict separation of CSS, HTML and JS means things like class names drift. With a JS build system you can easily introduce tooling to combat this (auto-removal of unused styles, enforcing that all classes are used, linting for CSS code, etc).
I just can't imagine building an app of more than a few thousand lines without a framework and frontend build tooling. I would end up needing to reinvent these tools myself to ensure code quality as the project grows. I'm not saying it's impossible to add these features into, say, a Django or Rails app, just that it's more work for a worse outcome.
I mean, maybe? Depends what you mean by "many". I'm certainly not advocating for adding JS & frameworks where interactivity is not needed, and as I mentioned, for less than a couple thousand lines, an SPA framework is almost definitely the wrong choice. But my experience in the last 10 years is that very few projects do not grow to the point of requiring quite a bit of JS for interactivity. Async requests, complex client-side form validation, comboboxes, dynamic modals/content previews, showing/hiding long content, 3rd party integrations... these sorts of requirements are in nearly every app these days. And the HTML/CSS only solutions are just not good enough yet, unfortunately.
> And using a backend framework for templating is not mutually exclusive to using a JS build system for helping transpile files and purge CSS and such.
Sure, but at this point, why are you avoiding introducing a JS framework? All that stuff is built in to most JS frameworks (but not backend frameworks). You could piece it together yourself... but for what benefit?
Related, the junior FE devs want our web app to be a SPA because they think it’s the only idiomatic way to write reusable components (think a JSX-written React component). Often they’ve never used anything else (so like TFA mentioned, for them it’s not an open choice).
I hate that my job these days has to involve counteracting this notion, probably looking like some weird Luddite in the process, for simply highlighting the same points from TFA.
Lots of hype from people who obviously never managed a real website or a real-world software project.
On the non-technical side, traditional server/client separation is well understood by everyone and has all the tools any team ever needs, while SSR takes some learning -- it is added cost that does not transfer in many places.
On the technical side, SSR only has clear advantage for very specific scenarios, e.g. e-commerce site where rendering time and responsiveness across different devices is a top priority. For the vast majority of websites out there, SSR likely only increases your server load and cost when you could leave all the rendering to client which is free resource. As browsers and computers themselves get faster, you don't even need to do anything to get better performance on client machines. Otherwise, this does not matter any more than Pepsi vs Coca-Cola or vim vs emacs.
If SSR is clearly the better choice for a team/product, go ahead, otherwise don't waste time on it.
Since the dawn of time, backends running on PHP/Java/Ruby/etc… were used to render pages serverside and send them to the client, maybe even sprinkled with a little JS.
Now that the whole JS stack and ecosystem has grown so big and unwieldy, we search for solutions to the problems we have created.
Added to that, many have huge incentives and lots of skin in the game, and many have only knowledge of JS and nothing more, so we try to reinvent the wheel again.
This is common in tech.
Decades ago, companies rented time slices on beefy servers. This was called “mainframes”.
Today, it’s called “cloud”.
Why do we need node.js-based SSR and hydration etc these days? It seems it's just remaking an already solved problem with fancier terms, bottom line is that it's way more complex, what's the point?
and before you black and white nerds jump on me, Im not talking about biotech and healthcare!