Server Side Rendering?

What was before SPA? Old-plain Server Side Rendering. Simple HTML. Simple CSS. Warm Sun. Green Grass. And just a few drops of JS.

Could you please answer a few stupid questions? I’ll guide you:

Q: After the first page load — is “the picture” customer sees the same for SSR and “SPA? Is it identical on HTML level?

A: Yes. Both solutions are looking absolutely the same!

Q: After the “second” page load — is “the picture” customer sees the same for SSR and “SPA? Is it identical on HTML level?

A: Yes. Yet again they are looking absolutely the same!

Now, be ready for the main magic, for the main question

Q: How much JavaScript you have to download, to render SPA Page?

A: A megabyte. With easy! Nowadays — maybe more.

Q: How much HTML you have to download, to render the Page?

A: A kilobyte. Or something about.

SSR can provide the same experience, the same result, for a customer, in cost 100 times lover, in speed 100 times faster, capable to run on any device. Proven by old-school sites, my grandma’s PC could open.

It should be clear — the best experience could be achieved with SSR rendering, and only “then” — SPA with code splitting. The difference, especially not for bleeding edge devices (and networking) could be HUGE!

Even more — SSR, without any JS sent to the client, is the best code splitting ever possible, as long all the things were left on a server, and nothing not crucial(only HTML, CSS, and images are crucial) have been sent to a client.

You can use any library you want, regardless of size, moment.js for example, and still fit to 1kb networks traffic limit. You are FREE!

Code Splitting with SSR

So. You have implemented SSR for your site, but still have to convert static, I would say dead, HTML to the dynamic React App. Static sites are dead sites. So you still have to send megabytes of JS, still want to run it, and still want to code split.

Suddenly – its not as easy, as before. Why?

Complexity of SSR friendly Code Splitting

How SSR now works? In short – you render a page on a server, send it to a client, load js needed, then hydrate HTML and it’s alive. Bingo!

By the time you call hydrate – all scripts have to be loaded, so you have to know all the chunks needed to render some page in some state. That’s why you have to use “code splitting libraries” — they will help you keep track on chunks used. That’s not so easy as it could sound.

Modern React code split libraries, like React-loadable, loadable-components or react-imported-component capable of doing it. They will use different approaches to collect and report chunks needed for current render call. But!, even if they work differently – the end is always the same – a single command to await all used chunks.

To actually render the page, user is already could see due to SSR, you have to load all scripts, to be able to re-render this page again. To be able render exactly the same picture you already can see.

So – page is ready, but you are waiting for scripts to be loaded. This is time-to-interactive. Worst seconds you can see anything, but could not do anything….

For most of us, for me for example, the main words here — load all scripts. If you want to dive deeper into the problem — I’ve got another article about it.

And don’t forget to dig the problem from JavaScript point of view:

But, today, lets focus on another sentence, nobody (realy! look like nobody) gives a shit before — user is already could see the site due to SSR.

Someone actually thinks — that is bad. That even page generation could increase Time-To-First-Byte or Time-To-Interactive, as long you will “spend” more time on server. Have a look on this thread. Then — I will explain what is wrong.

What is wrong here?

1.5s seconds spent in renderToString . Old-school php-maden web sites usually took no more that 300ms to full render.

. Old-school php-maden web sites usually took no more that 300ms to full render. Might be that was not renderToString , but full cream render ? Don’t use it.

, but full cream ? Don’t use it. Component approach — is wrong here. Component approach creates a problem, then you have to first render everything, and only then get information about page title you provided to react-helmet.

One simple mistake in the code.

Mistake is quite simple — you don’t have to render before you renderToString , you don’t have to inject rendered string into the bigger template. You may, and have to be “linear”. And you can send “top lines” of your page just as soon, as it possible, and send everything else a bit later. Let client start downloading bundle. Let client see Title before you finish render-of-everything. Like sui-components’s SSR packages does.

Anyway. Lets assume that we have server-rendered page. And the main point here it quite simple and straightforward. It’s hard to deny it —

The page is ALREADY rendered.

That’s the point! Everybody should wait for all scripts to be loaded, to be able to render the page back, but it’s already rendered. It’s already here. What if you could reuse it?

“Reuse” not as rehydrate reuse it, but reuse it for code-splitting!

Idea, I am talking about is super simple

Each AsyncComponent , basically, is a div . With “async result” inside.

, basically, is a . With “async result” inside. For client side AsyncComponent is empty in the beginning, and got filled then “async” operation resolves. It chunk got loaded.

For Server Side AsyncComponent is NOT empty, that’s why we have to wait for async operation competition on client side to match the result HTML.

As long AsyncComponent is not empty, it will be not empty in HTML sent from server, and could we just keep innerHTML of the div used to wrap around component, and display this “memoized” value while JS is being loaded.

of the used to wrap around component, and display this “memoized” value while JS is being loaded. Don’t display “spinner” or blank space, but render the actual content, AsyncComponent will have to replace exactly the same HTML, but in the future, when chink got loaded. But, while future is not here — display content we get from innerHTML .

will have to replace but in the future, when chink got loaded. But, while future is not here — display content we get from . In any moment of time we are displaying the same content. No visual changes. It works as common code splitting, but you don’t have to wait for all the chunks to be loaded in front.

SSR-friendly code splitting always was a hard and fragile, from some point of view, thing. And always work in the form — all-or-nothing. With approach I am talking about you don’t have to wait for all the chunks to be loaded first — you may start executing incoming chunks on receive. Or even not execute javascript, capable to render some part of your application, as long that content is already rendered, and useful for a customer even while it exists in the form of static, dead, non-reactive HTML code. No rules. You are free.

React-prerendered-component

This is library, I am talking about. Pre-rendered component. Keeps rendered content, it had inside, when it is not “live”, and starts rendering children only when you ready to go live . The only tricky moment here — you are controlling live prop. And as I said — you may “go live” only then user clicks or points on content. That’s up to you to decide.

This is not quite compatible with random code splitting library, and long they usually are not exposing loading promises , and the only way to get it — call to static preload , you probably should not call before some component “mounts”. But small, 10 lines long stateful component should do the job.

How it actually does this magic?

The main blocker for this pattern was the pattern itself. In React you could not access your DOM node, and read information from it, unless you render it. And if you would render it — you would wipe all the information existed in that node before.

PS: in this case “that” information “exists” only for React 16 hydrate call, and only on the first render.

To make it possible I’ve used “location IDs” provided by react-uid library, which helps me create divs with well-known IDs, I could querySelector in component constructor, and prefetch innerHTML before React will take control over it. And wipe it eventually.

More details, as usual, in another article. It’s not so easy as it could sounds.

SSR Code Splitting Conclusion

You still have to use SSR friendly code splitting library, as long it’s better to be able to load used chunks in parallel. That’s becoming a not crucial, absolutely optional thing, and most of application, without deeply nested code splitting could stop using any magic tools for keeping track of used js.

But not CSS. Don’t forget about CSS.

Preloaded-component gives you more time to load stuff, including scripts and data, before actually switching view.

But it actually not the all it does.

React double definition problem

Let’s recall the original problem — you have to load JS to redraw already drawed information. I called it — React double definition problem.

You have to redefine already defined things. Render rendered. Draw Drawed.

But React Double Definition problem is… two problems. It’s Double Double Problem.

You have to load all the data you need to render already rendered information.

To re-render the page you have to load all the js being used, and load all the data being used. JS could be 1000 times “more”, than HTML its going to render. DATA… is not any better. I saw examples where hydrated normalised redux store was 100 times bigger than information rendered “from it”.

I would say — SSR just suck, as long you have to redo, reload, rerun literally anything. I am not sure SSR is a good thing. Kill it with fire, please.

ANYTHING, you made on server —is useless! Just trash it.

This is very common today, die to the way SPA fetches and consumes information, but was anti-pattern in jQuery Era.

jQuery doesn’t call to REST or GraphQL endpoints. jQuery just read all the things from data attributes you left in HTML. jQuery just traverse DOM and restore data from HTML. jQuery is so jQuery. I couldn’t say It did all the things right, but somethings were… they were useful, and I am still happy using them. Every time I have to refactor 10 years-old-site – it becomes bigger(FATter) and slower due to all “architecture” we “have” to use today.

That wasn’t a thing 10 years ago. You fathers were wiser than we are.

Probably — if you used some data(state) to render some data(HTML) — you are able to restore source data(state) from the derived view (HTML). Or, at least, partially restore it .

You may use your own rendered page as a source for your state. Just store some invisible, but important data pieces in invisible attributes or tags.

That is actually an edge case, but I was interested in “hydrating” not only HTML, but the State. It’s relatively easy to hydrate and send from Server to a Client Redux store(thats built-in feature), but close to impossible to send “internal component state”, as long there is no place you can store it. There was no place.

In the first example we are using jQuery like way, and just scanning information back to state.

The second example is a bit jQuery-ish, and actually stores JSON next to element.

Both capable to store “internal component state” on server side render, and restore it on client. Something you were unable to do before. Something you were able to do before the before. Back to the Future.