How quickly a user sees something when your website loads is invaluable. Studies from 2006 found that most users will abandon your site if it hasn’t loaded in 3 seconds. Unsurprisingly, users haven’t become more forgiving in the last 13 years.
Unfortunately, modern web frameworks like React are pretty bad with page load speed out of the box.
But all is not lost, you don’t need to drop React to have fast page loads. There’s lots you can do to speed up your page load — this post focuses on Static Rendering, a variant of Server Side Rendering.
Static Rendering is basically Server Side Rendering done without a server. So let’s first of all explain what Server Side Rendering is.
This means that there’s a long period where the user is just looking at a blank page. Users don’t like looking at blank pages — they have places to be, memes to enjoy.
Static Rendering is basically just pretending you’re doing Server Side Rendering, but doing it all at build time. In other words, when bundling your app you run a local server, check what all the HTML is, and then put that HTML somewhere.
Compared to traditional Server Side Rendering, this has a few downsides:
but also a few upsides:
To make our lives at Thread easier, we created a tool to do this static rendering automatically for us, alongside our normal webpack build. We open-sourced it, so feel free to give it a spin: @teamthread/react-static-render-plugin.
To use it, we take our old React Router code:
and we replace it with:
import render from '@teamthread/react-static-render-plugin/render';<Router><Route ="/" = /></Router>;
and then we add a new plugin to our webpack config:
const StaticRenderPlugin = ;moduleexport =// ...module:rules: loaderRulesplugins:// ...pages:'index-signed-in':path: '/'locals: signedIn: true'index-signed-out':path: '/'locals: signedIn: false;
and we’re done! Webpack will now build us a
index-signed-out.html, alongside our normal build assets.
The next challenge we have is that we want to render some components differently when static rendering. For example, we have a component that encourages you to sign up to Thread by offering you a discount.
The discount amount, however, is actually a dynamic value provided by the server. We don’t know what it is at build time.
Fortunately, our plugin sets a global
STATIC_RENDER environment variable, so
we can replace:
<li>Register to get amount off if you order within 3 days</li>
<li>Register to get processenvSTATIC_RENDER ? '—' : amount off if you orderwithin 3 days</li>
Generally, we want our statically rendered app to be a watered down version of our full app. By gracefully adding more to the app when going from the statically rendered version, and the full version, we can make the whole page load feel very smooth to the user.
Ideally, the user shouldn’t realise that any transition happened at all.
We used @teamthread/react-static-render-plugin, and you can too — give it a spin!