A few weeks ago, Kurio front-end developer team starts working on a new web app project written in React. It’s all fun and games until when we deployed the alpha version, our product manager tried to share a content from the web app to Facebook. It turned out the Facebook post showed no thumbnail, and only default title of the web app, not the title of that particular content.

Uh oh. The web app tested on FB Sharing Debugger

What went wrong? Isn’t this supposed to be a “simple” function?

A little background

When we share a URL to Facebook, the social media will send it’s scrapping bot to that URL and fetch certain informations from the HTML page. Usually it’s these three items: title, thumbnail, summary.

In order to standardize this process and avoiding steps where its bot have to guess which part of the HTML is the title, which part is the thumbnail and so on, Facebook introduced Open Graph meta tags, which allow web developer to put a special <meta> tags to tell Facebook bot which one is which. This <meta> tag value is dynamically set according to the URL of the web page.

And that’s the problem. React web app takes form as SPA (single page application) where the DOM and content is rendered by Javascript. It means when Facebook bot visit the page, it will only find the bare HTML tag of React app placeholder. The bot has no Javascript rendering capability, so all of the React goods will never be executed, leaving the bot clueless about the content.

Regardless the URL that’s being shared, the Facebook bot will always see this

Server Side Rendering

Actually React already have its solution regarding the issue. In early days of React, when developers flock to React and rewrite all of their websites into SPA, they found a big problem; the SEO won’t work. The root of problem is essentially the same; the Google bot won’t see the content when indexing their URLs. So the React team developed a solution with new ReactDOMServer module. This solution, combined with usage of NodeJS web server (Express, in our case) is widely known as Server Side Rendering (SSR).

In simple words, SSR provides ability to render React components from a NodeJS web server. Usually on normal case, those components will be rendered on browser side, replacing the bare HTML page. By rendering on server side, instead of that bare HTML page, the browser will receive full final HTML DOM of React components rendering. This will allow bots with no Javascript rendering capability like Google’s & Facebook’s to get the correct content for them to process further without even needs to execute React scripts.

All those goodness come with one major caveat: we need to rewrite almost all of the project.

That’s because when developing the early version, our front-end team only focus building on what they’re good at; the browser. When we want to implement SSR, we need to breakdown almost every components to be somewhat platform agnostic, so the Node environment can handle them too.

This turns out to be very complicated thing, especially in the case of routing. On the client side, we use React Router to route request URL into the correct component. React Router uses window DOM to store history of the page navigation. This won’t work on NodeJS environment since it has no DOM feature. After a few initial tweaks, we end up duplicating the routes that we declared in React Router to Express equivalence.

This is not okay. Especially in terms of maintainability where the front-end developer team needs to convolute their supposed to be client-side only code to accommodate this needs.