There are cases when server-side rendering (without SPA) is easier and faster. For example: documentation sites, blog-like sites, internet stores, sites like Hacker News. In all these cases, you can save on development time by writing just one application instead of two (server and client), and improve performance (no need to load multimegabyte JS applications and make multiple AJAX requests to display a page).<p>Of course, there are cases when SPA-style application is better, for example: (graphic/circuit/text) editors, IDEs, mobile newsfeed-based apps - everything that resembles an app rather than a page with text, menus and images. But in these cases you usually don't need server-side rendering. And sometimes you cannot even use it - for example, if your code needs to know browser windows size to arrange objects on the page.<p>So I think that SSR (running JS on server) is rarely useful.
I've been saying it for years - the hard part is not "server side" vs "client side", it's making sure the state stays consistent between those 2 buckets.<p>If you want to remove the hell from your life, you need to be all in on one or the other.<p>For us, we've been keeping all state server-side using things like Blazor and hand-rolled js-over-websocket UI frameworks. We never have to worry about more than ~10k users, so this works out great for us.<p>If we were webscale, we'd have to consider client side options.
I've been using server-side rendering for many years now and I find it to be almost zero overhead at this point. Yes, I had to do some initial work to set things up, but these days I don't even remember it's there.<p>Most people make an assumption that in order to have SSR you need to run JavaScript (e.g. Node most of the time) on your backend. That is not a valid assumption.<p>I think the title of the article could benefit from adding "using Node", because much of the complexity described is something I do not encounter at all. I'm using Clojure and ClojureScript with Rum as a React interface. Much (if not most) of my code is in cljc files, which get compiled with Clojure (for JVM on the backend) or ClojureScript (for JavaScript on the frontend). And the ClojureScript advanced compilation takes care of only including what is strictly necessary in the frontend compiled JavaScript.<p>I mean, sure, you need to be careful not to do stupid things like trying to read from files, but otherwise I just don't encounter much friction. And I reap the benefits of using a single language for both backend and frontend, with most of my data model (e.g. business logic) code written only once, with SSR being a nice cherry on top.
I make a difference between website and webapp.<p>a website is a collection of webpages, where the maingoal is to display some mostly static information (i.e. an article)<p>a webapp has the main goal of managing and reacting to a complex, non trivial user state.<p>website, go server side all in, do not add the tax of client side rendering / hydration to the frontend. if necessary embed small enclosed client side webapps on the frontend.<p>webapp, go client side all in, screw server side rendering.<p>yes, you can marry website and webapp via server side rendering / hydration. but the cost to make this really really fast and spiralling complexity and edge cases, does not make it worth it.<p>choose the right tool for the job, and just because it has web** in its name, does not make it automatically a job for react/angularjs/newest-coolest-framework
<a href="https://htmx.org/" rel="nofollow">https://htmx.org/</a><p>Having spent 36+ years in the computer industry, I consider the advent of htmx to be the first thing in web development to to attempt to pull the industy's head out of it's ass.<p>Don't forget to include a solid remake of css in your project like tailwindcss. It also makes code much more readable.
> After a fashion, it was decided that sometimes our HTML is best rendered by JavaScript, running in a user's browser. While some would decry this new-found intimacy, the age of interactivity had begun.<p>I didn't get the memo when this was decided, and I'm still unconvinced.<p>Let me see if I get this straight:<p>The main reason for client-side rendering is that some web applications don't want to do a full page reload every time that there's a non-trivial state change (usually triggered by user interaction). When the inherent complexity of the application means that there are state changes pretty often, doing a page reload so often would just kill the user experience, and using jQuery or similar libraries would lead to a spaghetti.<p>Is that the reason for client-side rendering being the "default" in the realm of modern javascript?<p>If that's the actual reason, then that seems reasonable, but I think that Javascript culture (frameworks, tutorials, articles) usually erroneously assumes that every application is a complex one with tons of state changes, thus assuming that client-side rendering is the only right way to develop an application (without counting "isomorphic" SSR which is just another way to create a spaghetti).<p>Sure, if I don't like it I can just move over to Django, Laravel, etc. but it feels like I never get an actual explanation of <i>why</i> client-side rendering is the default in these js frameworks, it's just accepted as a fact of life.
Except for the confusion about terminology the article has some good points.<p>We had an idea a long time ago in the web dev world that we could run the same language in the browser and in the backend. Basically reuse everything and save time.<p>It think this is bad assumption to begin with.<p>If I have a clean separation between frontend and backend, regardless if doing mostly server rendering or client rendering it is only one thing that makes sense to share, input validation code.<p>Like what is the definition of a first name, last name, age, price, email address etc. That is the one thing that need to be in agreement between the frontend and the backend to be able to exchange data.<p>But to share frontend and backend technology for only the gain of input validation seems like a heavy price to pay for little gain.
Shameless plug: If you want seamless SSR with Django logic, but React templates, check out my project at <a href="https://www.reactivated.io" rel="nofollow">https://www.reactivated.io</a> .<p>It's like HTMX but uses React, and the JS bits <i>are</i> rendered on the server. You can then hydrate on the client.<p>The Reactivated docs site itself uses the project: <a href="https://github.com/silviogutierrez/reactivated/tree/main/website" rel="nofollow">https://github.com/silviogutierrez/reactivated/tree/main/web...</a>
The complexity of web development frontend itself is just absurd. The mess of dependencies, the mess of language transpiling, opaque abstract functions with unreadable call stacks, asset management, sync vs async, the random best practice of the week, etc.<p>I look at the state of web pages and apps and it's not even for the betterment of user experience! Hacker News and old.reddit.com still provide the smoothest, fastest experience at the cost of having to zoom in every once in a while, but the price is worth it.
I gave it a shot at one startup using next.js that wanted to pre-hydrate redux state, but also use tracking with session cookies et al the regular bag of beans. I spent maybe 6 weeks on it and basically I grew to realize I was in a miasma of pain. I didn't last much longer. I could've wrote the entire thing just vanilla js/css in probably a weekend...<p>So I can commiserate with this.
I opened this thinking it would lament the challenges of server side frameworks and templating.<p>But those things seem so, <i>so</i> sane and simple compared to the mess I just read about. It's worse than I could have imagined.<p>Who thinks that's a good workable solution? Who's idea was this?
I find this a very insightful application of the concept of colours to look at the problems of mixing code meant to run on slightly different and subtly incompatible runtimes, within the same code base, without calling out this distinction of "colour" by any particular mean of syntax, or tooling, or explicit documentation.<p>It's a good observation that helps, at least me, shed light and give a name to this problem that many will have experienced and struggled with.
The moment you need SSR, you'd be in a better place if you were using just plain old server rendered (componetized) views, such as the ones you can do with laravel's Blade system, and do your client side interactions with Alpine and your server interactions with unpoly/HTMX.<p>SSR per se is not a "big problem", specially if using something like Next. The problem comes when you have to mix in translations, i18n, data fetching from external sources, authentication, cookies forwarding, etc, etc, etc... in my opinion complexity grows so exponentially that I don't see the advantage anymore.<p>I'm working on a project built with Laravel + Tailwind + Unpoly + Alpine and it is such a walk in the park to implement anything thrown at us. Although it is not "cool" tech, so some people around here don't want to work on it because they only want React all the things :-s
In Javascript SSR, if you need the same logic on the client and server, define an API module + interface. Make a different API bundle on the server that calls NodeJS functions, file reads, whatever, directly. Make an API bundle on the client that makes AJAX requests to your API endpoints. Now your Javascript can call the same `api.fetchWhatever()` method, and await the result, and it works on the client and server (if you need it). It's a very nice pattern.
SSR is the dumbest thing I’ve ever heard of. Client and server are different things, treat them that way. The whole web dev community keeps tripping all over itself to make simple things wildly complicated.
> If you're considering using one of these frameworks, I would recommend you carefully consider if the complexity is worth it, especially for less-experienced members of your team.<p>Far too many folks seem to believe that complexity is a binary choice or that it can be avoided wholesale by choosing frameworks (or lack-thereof) to solve their problems.<p>Truth is, when you're building software on the web, you're gonna have gonna have to make a series of decisions on where the complexity that you'll inevitably encounter should live.<p>We're all simply making tradeoffs on where that complexity lives: the browser runtime, the build system, the type system, the server, the platform, their framework, your framework.
I'm convinced SSR is only a thing because of Lighthouse scores.<p>Client-side rendering with client-agnostic REST APIs is a fantastic architecture.<p>But noooooooooo we can't have nice things
In this thread: people confusing server rendering (like your old PHP) with SSR (same Javascript codepath for client and server, i.e. Next.js)<p>One is easy, the other is the definition of leaky and crappy abstraction. This article is about the latter technology.
I already know I'm off my rocker (and my lawn with that phrasing) but I really wish the browser supported Python as a language instead of Javascript. I can pickle Python, send it to a client, and run it. Combine that with everything else Python 3 has brought to the table and I'd have a language that runs client side that I can depend on and that I love.
I agree with the Next.js people in that thread<p>SPA+SSR has never been easier, and my experience (as of this year) is that its as easy as static websites. Even easier in some cases with making the CSS easier while all the bundles and optimizers to make builds are hidden.<p>I think people need to rethink how they design their websites and complete concept of a viable business.<p>I get the sentiment of the absurdity off web development but its successfully been abstracted away if you keep your app and idea simple. If you’re still doing gigantic web 2.0 apps with hundreds of views, microservices everywhere and API calls going every which way, thats the problem. The stack for those is ridiculous and not even necessary anymore. You can drive [hundreds of] millions of revenue without any of that these days, without even a user account flow or state management, the market is trying to tell you something.
whats the reason behind all this endless JS race that s been going on for years. I only had to use it once and it felt like everything was prematurely overabstracted ending in more code doing less. It made me run back to php+jquery, which is more like a car engine rather than an modern abstract art statue.<p>is it the overabundance of programmers? the fact that it makes them look busy? people liking wasting time recompiling most of the day? overengineering making people feel superior? it certainly doesnt feel healthy and makes one question whether the whole SV startup ecosystem is a cargo cult built on shaky grounds by people who are just apeing each other on everything, from design to backend.
Do I live in a parallel universe where building SSR/SPA sites with Next.js is somehow incredibly complex? I know below the abstractions there is complexity, but building SSR rendered SPA's today with something like Next.js has never been more simple. I think web development has taken a huge leap forward where we now have stable tooling, a strongly typed language with TypeScript and top notch boilerplate free state management with MobX. To top it off you can write performant backend API's in Node.js with again TypeScript sharing contracts (Interfaces) between backend and frontend. I for one am really happy with the current state of affairs.
The complaint in the article is technical, but my issue with the SSR + hydration approach is that it doesn't actually work for the users. Mainly because if you need a page that is indexed by Google, there is a high chance your users will browse it and open pages in new tabs. So the approach of "there is a small initial penalty, but everything is faster later" no longer applies -- you get that initial hit quite often.
What an incredibly boring, prosaic post which is almost completely devoid of anything useful. In fact, over half of the post is just the author waxing poetic about some tangentially related things. His arguments boil down to "To me, this seems like a bad idea."<p>Well, OK buddy. Then don't do it. Meanwhile thousands of web developers have been doing it for years and it has never been easier.
What is meant by "server-side rendering"? Is it the same as server-side on-demand html generation?<p>If so then I think the term "server-side rendering" is somewhat confusing. Your server is "generating HTML", not 'rendering" it.<p>Rendering in my view means turning code (like HTML) into visual output.. So whether the server serves always the same HTML, or regenerates it for every request, or something in between, the client/browser still has to "render" that HTML into visual output.<p>True server-side rendering I would think should mean the server renders HTML into a gif or jpg which then gets shown in the browser.
I've been testing out Alpine.js recently and find it to be very nice to use. You can have reactive state and most of the conveniences of React, but all in your HTML without a build step.<p>I work with SSR React professionally and many times I yearn for being able to just use good old fashioned templating engines and client side Javascript - no builds or anything.
See <a href="https://remix.run" rel="nofollow">https://remix.run</a> for a modern, sane, progressive approach to server-based rendering w/ as-needed hydration.
Honest question: it's clear to me that the term SSR has been repurposed to mean this complex "generate html reusing ~same code on backend/frontend and then hydrate it" thing. What do we call the classic style where the server just renders html using a template language?
Since the post mentions Next.js, it's worth calling out two streams of ongoing work that solve major painpoints of SSR:<p>1. A filesystem convention (`*.server.ts`) for more cleanly separating client and server component trees<p>2. The introduction of a Web standards runtime[1] for SSR.<p>If anything, we're entering the best generation of SSR ever. We'll see new generations of apps shipping less JS to the client, rendering and personalizing at the Edge, closer to the user, and the infrastructure to support this will be serverless and economically every efficient.<p>[1] <a href="https://nextjs.org/docs/api-reference/edge-runtime" rel="nofollow">https://nextjs.org/docs/api-reference/edge-runtime</a>
Come on, Trisomorphic rendering or Distributed Persistent Rendering are pretty simple, basically these are just [insert joke about monoid in the category of endofunctors].<p><a href="https://en.wikipedia.org/wiki/Hydration_(web_development)#Trisomorphic_rendering" rel="nofollow">https://en.wikipedia.org/wiki/Hydration_(web_development)#Tr...</a><p><a href="https://www.smashingmagazine.com/2022/04/jamstack-rendering-patterns-evolution/" rel="nofollow">https://www.smashingmagazine.com/2022/04/jamstack-rendering-...</a>
I figured this out several years ago when I tried to build a full-stack framework to seamlessly connect the front end and back end into a single development experience (kind of like what Meteor and Next.js turned out to be). I ended up cancelling that project, pulled out the RPC + pub/sub internals and spun it off into a separate set of libraries which became successful on their own.<p>I've been saying this for years. Although code reuse is possible between server and browser and sometimes it saves a lot of time, it's not common enough to be a default (as part of a monolithic framework) and there are security implications which make it highly desirable to differentiate between the two.<p>I do think frameworks are overused. IMO, frameworks make more sense in DevOps for infrastructure orchestration to provide resilience and scalability. For example, I think Kubernetes makes sense as a framework - Critiques of its complexity are not related to its frameworkness; there is literally no other way to do orchestration - Orchestration is the top layer which runs everything and sits above everything (including hosts and processes). Frameworks don't make much sense in development space IMO; they're mostly a way for companies to achieve lock-in.<p>Even on the front end, Google Polymer had already proved through their WebComponents polyfills that frameworks were not necessary to achieve reactivity on the front end. A simple, lightweight library is usually enough.
The original server side rendering (HTML rendered on the server by your choice of language) is simple, efficient and most sites on the internet still use it, including this one.<p>The article is talking about ‘modern’ js style server side rendering combined with client side rendering, which is of course a huge dumpster fire and encourages absurd complexity on both sides of the equation, starting with the fact the app is split in two.
This could probably be mitigated by a combination of algebraic effect handlers and session types for effects.<p>Algebraic effect handlers let you dynamically (re)define how effects are handled for a given piece of code.<p>and<p>- session types for effects, that would let one specify protocols for effects (i.e. a HTTP response handler would not be granted access to the socket, but would be allowed to use dedicated effects: `statusCode`, `header`, body` and `trailer` effects and would not be allowed to use them in a way that violates HTTP. Session types let you check that at compile time.
This isn't real "server side rendering". This is just generating simpler HTML. Real rendering on the server would mean sending a canvas or an image or video, like "cloud gaming".<p>All this complexity seldom translates into sites that do much. There are real "applications in the browser" that let the user do something, but those are rare, and most are toys. Most of them could have been written in Flash, anyway.
Front end complexity - Making applications isomorphic so you can re-use code on the client and server<p>Hacker News commenter: Ugh, why is this problem so over-engineered. It's completely unnecessary<p>Back end complexity - Two hour Google article from yesterday that goes through layers of C++ and raw assembly that results in a 2-3% speed up by basically using SIMD and turning off branch prediction<p>Hacker News commenter: Wow! So cool!
Nexus DocUI is server-side defined, but client-side rendered. It doesn't have real-time updates yet, you have to reload the page, but I'm working on a plan to implement that. Currently renders the front-end with Flutter, the back-end could theoretically be any language since it sends JSON to the front-end.<p><a href="https://nexusdev.tools" rel="nofollow">https://nexusdev.tools</a>
The common mistake teams make getting started with server-side rendering for React is thinking that your <i>entire</i> backend has to be contained in a single JavaScript bundle. Instead, use any language you want to set up your APIs and business logic. Then set up a fully independent pool of servers running Node.js whose only job is SSR. This setup skips over every problem the author mentions.
SSR feels like an echo of JSF (that's JavaServer Faces for you youngins) - an exceptionally complicated way of doing simple things. IMO, SSR will follow the same arc in history - a brief period of popularity, followed by a lot of "what on earth were we thinking". Client side rendering is much simpler and cleaner.
Laravel livewire / Phoenix liveview and a lot of new frameworks are now focusing on bridging this gap between ssr and clientside - almost trying to make it seamless.<p>Though only time will tell, what can of worms that will open later.
The only thing 'absurdly complex' about this is the Javascript portion. Server side component based frameworks exist and work very well for this purpose.
article crticizes "the absurd complexity of server-side rendering" by starting with "In the olden days, HTML was prepared by the server..."
my personal worry, could be unjustified, but SSR seems to be much less secure compared to plain old client side stuff. sure, static client side is less seo friendly but...not going to compromise your servers! considering the fast moving and relatively patchy security of npm ecosystem...things like prototype pollution vulns are alerted almost weekly if not daily and you are lucky if a fix exists that you can upgrade to!
Hum... You mean JS needs generic monads?<p>TypeScript supports them, doesn't it? This shouldn't be too hard to fix, but it's a matter of rewriting or encapsulating all of the core language's API.
Sorry I'm gonna just stick with server-side rendering with Django templates. All web development 'advances' are a treadmill to nowhere, waste of time.