Hacker News new | ask | show | jobs
by mottomotto 3130 days ago
If you're on the fence about server-side rendering being needed for your webapp don't do it! As a team of two with one engineer, I decided YAGNI and instead focused on the responsiveness of the React and Redux-based web application. It is very snappy to load and our (paying) customers are happy.

You might not need SSR. I don't. I expect there will be more work to optimize it and eventually it'll be obviously a good idea. But you don't need it right now if you're working on a SaaS product.

4 comments

It's the other way around: you might not (in fact, probably do not) need React.

Start with server-side rendering, and move to React if your application's dynamism demands it. Most applications don't. It's painful to see so many websites building huge, slow, JS-rendered monsters for one or two dynamic elements per page. Unless you are Facebook (and have your JS cached within one hop of every internet POP in the world), server-side rendering is going to yield performance wins for nearly all visitors.

Well that is a whole other debate. The best thing about React is common patterns. Second best is the availability of components. I've worked with JavaScript for a long time -- the Backbone.js days were painful. It was easy to accidentally leak event binds, code yourself into a corner, etc. The jQuery days were almost better in some ways but still had some real pain points.

You missed that I'm working on SaaS and a web application. Client-side state is important -- each of my customers can load up most of their state to client-side and the performance is great. This is the whole point of client-side apps. Get rid of all that round trip latency sending HTML to the client of every click. Get rid of your complex server-side framework. Client-side is simpler if you learn and embrace it (and don't need server-side rendering). It's also much easier to have a consistent UX with client-side state.

So use what is appropriate for you use case. For mine, that is 100% client-side no doubt. You can't beat the performance for an application.

"You missed that I'm working on SaaS and a web application"

I didn't miss that. SaaS means "software as a service", and doesn't imply anything about the complexity of your UI. Plenty of SaaS companies use server-side rendering. Likewise, "web applications" were being written long before React was a thing.

Also no, you don't have to do a full server round-trip for every click, any more than you have to send JSON back to your Reactionary UI for every click.

So sure, if you can truly load all of your data in one big JSON blob and do everything else client side, then I guess you're in the 5% of people who can benefit from React. The other 95% should use a good server-side rendering framework and get things like low latency, URL routing, progressive enhancement and SEO-friendly pages for free, and build the few dynamic elements on their pages with a simpler, more robust technology. I never said that React isn't useful, just that it shouldn't be the default choice for most people.

But I have zero use for SEO-friendly pages -- all my client-side pages are behind a login-wall. It isn't one big blob of JSON -- it's multiple endpoints. With HTTP/2, multiple small requests are fast.

> build the few dynamic elements on their pages with a simpler, more robust technology

This is a horrible idea that has worked poorly for so many projects. At one potential employer, they did this and their app had a message view with a read count. They didn't care the read count didn't update -- you had to reload the whole page for it to update. Those are the kind of inconsistencies that the above approach encourages because it's not cohesive.

Can you do it? Yes. Should you? No, not in my book.

> low latency, URL routing, progressive enhancement

I've got low latency, I have client-side URL routing, I have no need for progressive enhancement -- it's just more complexity that neither I nor my customers need. These are all great ideas if you have a public website and need to cater to a wide range of visitors. I don't. I'm very happy to be able to only have to support the last couple major versions of each browse.

"I've got low latency, I have client-side URL routing, I have no need for progressive enhancement"

Again, maybe you're in the 5% of "web application" users that are not actually web applications, but rather, "browser apps that download some data once in a while". If so, great. Most people aren't in that group.

Also, just to clear this up: client side URL routing is not URL routing. It's an ugly hack to make up for the fact that you can't use URLs for their stated purpose. It's honestly sad that we've wandered so far from the norms of the web that URLs have lost their meaning.

It's not an ugly hack at all. It works well, the browser history works properly and the interaction is just as if the pages were being fetched from the server. At any point in time, the user can do a hard reload and the page will rerender as it did before. The URLs are the same as if I was doing server-side rendering.

So I would ask you at this point to turn this all around. Look at it from my perspective. I've been doing fullstack for more than a decade (professionally, hobbyist for twice as long) so I've done plenty of server-side rendering in frameworks like Ruby on Rails, ASP.net MVC, etc. I've contributed (as lead) to open source gems that have over 800k downloads. So I have invested a lot of time into the server-side.

But today, with client-side, there is a huge simplicity factor. You can only get to it after wading through the turbulent waters of "flavor of the week" client-side projects and noise. But when you do get through that and identify your pillars to build on, this is what you have:

* all of your complexity is on the client-side for web

* you can make a simple fairly clean REST or GraphQL backend that will work with multiple clients (web, mobile, etc)

* for at least REST, you no longer really need things like an ORM on the server-side as all of the endpoints are simple and basically fetching a single data type (I use SQL with PostgreSQL so I would say a table here but it depends on implementation)

* HTTP/2 reduces the cost of small requests so complex things like GraphQL aren't really necessary -- you can stay with REST without a penalty

Is there complexity? Is it different? Does it challenge the conceptions of those used to fullstack? Yes. But there is real value and simplicity here too that you might find if you're willing to put aside your hard and fast rules and try something new.

I've been a web developer since the beginning, so I understand this frustration with the current generation of web developer that reaches for React first purely because it's trendy with complete ignorance of the strengths of traditional approaches.

However, you are throwing the baby out with the bathwater. Client-side rendering saves server resources, and allows a single API to power web and mobile apps. A pure API is easier to optimize, and is generally a sensible separation of concerns. Of course this doesn't come without overhead, but you don't have to have Facebook-level complexity for this architecture to make sense.

The difference there is that it's very hard to port a non-JS server-side-rendered site to React if it turns out you do need to. Whereas it's relatively easy to port a React application to additionally do server-side rendering.
The other difference is that I'm having a hard time imagining a scenario where someone is getting blindsided by "damn, it should've been a SPA after all!"

I'd be wary of all of the technical decisions that were made if the decision-maker knew so little about the requirements that they couldn't even call that shot correctly.

Of course, on a long enough time scale, all bets are off.

> The other difference is that I'm having a hard time imagining a scenario where someone is getting blindsided by "damn, it should've been a SPA after all!"

I've seen it happen more than once. Start with what looks like a straightforward form flow, seems like it should be fine in rails or whatever. Then it turns out some fields depend on other fields, so you've got to dynamically show/hide parts when other parts are set. And doing a server roundtrip, even AJAXey, is just too slow. So you put a bit of client-side Javascript to handle that. And then as the product evolves the interrelations between the form elements become more and more complex and businessey, and you have more and more logic split or duplicated between backend and frontend.

This is something a lot of people just don't get. And with react's serverside render, you don't get a trashy 2010-era SPA, you have an SPA that is also an MPA. It's literally the best of both worlds with porting your redux to reactnative for Android/iOs just around the corner.
No matter what system you use for server rendered pages most likely you will have to hit a database just to render out the site. These days that's a bad idea when we should be building progressive web apps that can fetch and cache content as needed from services but the entire app can live offline and even cache data in local storage to enable it to have at least limited offline functionality.
That really is dependent on use case though. In my current project, I want the most up to date data possible so no caching. In reality, it is cached locally in the browser state and soon, I will be pushing data to update that browser state (based on other users activity in the same tenancy).

I think generalizing to "we should be building progressive web apps" is harmful. You should do what is appropriate for your use case.

> I want the most up to date data possible so no caching

This seriously doesn't mean "no caching" and shows a real lack of understanding about caching.

You state that people should so what is appropriate for use case, though your other comments here go completely against that and are cargo cultist in the extreme. I think perhaps, when you say "should do what is appropriate for your use case" you actually just mean "what I think you should do".

It is not the kind of caching that the post I'm replying to is advocating ("the entire app can live offline and even cache data in local storage"). I mentioned the caching I am doing to point out things aren't so simple. I do mean quite literally that none of my API HTTP responses have a caching header (assets are coming from CDN with very long cache life).

It might be more fruitful to try to explain why I go against that instead of simply saying I do without a rational argument that can be responded to. If anything, the thread pretty clearly revealed someone is extremely biased to server-side web frameworks and is unaware of the progression of client-side web APIs.

Also, if you _need_ SSR, rails might be a better approach. It's too bad the author didn't include it in the benchmark.
We did this recently with a small app that needs to be fast. The relatively simple page that you see when you first visit the site is rendered with plain old Rails, then when the user interacts with the page (based on DOM addEventListener hooks) it causes additional React components to be mounted and rendered.

Originally I’d hoped to be able to render a basic version of the page with Rails, then ‘enhance’ it with React - ie render <button>For</button> with Rails, then when React has loaded, replace it with a React component. But I couldn’t find any details on using it this way, and given time constraints choose the simplest option.

> then when React has loaded, replace it with a React component

What you described is basically `hydrate` which is how to enable React event handlers like onClick after a server-side render.

https://github.com/styfle/react-server-example-tsx/blob/4586...

This is something we've done in the past, and it works well. In fact, the ability to do this (usability is important to us so progressive enhancement is a lifesaver) is why we looked at react in the first place.
unless your startup's life and death depends on SEO - in which case, do it !