React + non-SPA websitesServer-side React in non-SPA websites
Server-side rendering — using a server to build static or prerendered HTML out of React component trees — is a feature of React that’s surprisingly easy to get started with. Although it’s frequently used for pre-rendering single page applications, let’s take a look at using this technique for non-SPA websites.
ReactDOMServer rendering methods
Server-side rendering with React is easy: React’s server-side rendering package is called ReactDOMServer
, and it exposes two methods for rendering a React component. These methods are the server-side equivalents of ReactDOM.render()
, however they return a string of the rendered HTML rather than mounting the component to a DOM node in a page.
ReactDOMServer.renderToString()
is the method typically used for rendering a SPA server-side. This method returns HTML with hooks that allow client-side ReactDOM.render()
to efficiently mount onto the available DOM without re-rendering everything.
ReactDOMServer.renderToStaticMarkup()
is a less-used method that returns static HTML without any extra hooks for client-side React. This method is extremely interesting if we consider that not every website needs to be — or should be — a SPA.
Non-SPA use cases
Where would ReactDOMServer.renderToStaticMarkup()
be useful?
Server-side templating
If you don’t need a React SPA client-side, rendering with React on the server is a forward-thinking approach. React is great not just for managing state within client-side applications, but also for architecting and developing reusable components across layers of abstraction.
Unlike the simplistic template partials or helpers offered by many server-side frameworks, React’s component and templating model encourages designing composable components, which I’ve found to facilitate reuse and ease maintenance over time. Let’s face it: find and replace for semi-complex HTML structures isn’t as nice as changing one encapsulated instance.
And as a bonus, front-end developers won’t need to learn the nuances of yet another language-specific templating language.
Static site generation
For convenience, I’ve been referring to ReactDOMServer’s rendering methods as server-side rendering, but do you need an application server that’s aware of React at all? For simple sites that might otherwise use Jekyll or another static site generator, there’s a case for React as an alternative.
As an example, this site is currently built with a simple set of scripts to orchestrate React in rendering each page at build time. This looks like the following:
import { renderToStaticMarkup } from 'react-dom/server';
import { Shell } from '../components/Shell';
const deleteRequireCache = path => delete require.cache[require.resolve(path)];
const prependDoctype = html => `<!DOCTYPE html>${html}`;
const renderJsxPage = async (filePath: string) => {
const p = path.join(__dirname, '../', filePath);
const { default: Page, metadata } = require(p);
const content = renderToStaticMarkup(
<Shell metadata={metadata}>
<Page />
</Shell>,
);
deleteRequireCache(p);
return { content, metadata };
};
import React from 'react';
import { Metadata } from '../types';
export const metadata: Metadata = {
title: 'Page title',
description: 'Page description',
};
export default () => <div>Page content</div>;
What the build script does is render each page (written as a React component) to static HTML. Each page is wrapped with a common template for the site’s header and footer, and this template receives metadata exported from the page’s own module.
The result is both performant and a pleasure to work with.