Server-Side Rendering
Learn how to fetch content from the server and render it in the frontend.
We'll cover the following...
We saw in the previous lesson that our application works and this is great news. However, the app is running only on the client side, which means that if we try to curl
one of the pages, we’ll see something like this:
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>My library</title></head><body><div id="root"></div><script type="text/javascript" src="/main.js"></script></body></html>
Output of the curl command
No content whatsoever! There’s only an empty container (the root div
), which is where our application is mounted at runtime.
Rendering the content
In this section, we’ll modify our application to be able to render the content from the server as well.
Let’s start by adding fastify
and esm
to our project by using the following command:
Press + to interact
npm install --save fastify fastify-static esm
Now, we can create our server application in the src/server.js
module:
Press + to interact
import { resolve, dirname } from 'path'import { fileURLToPath } from 'url'import react from 'react'import reactServer from 'react-dom/server.js'import htm from 'htm'import fastify from 'fastify'import fastifyStatic from 'fastify-static'import { StaticRouter } from 'react-router-dom'import { App } from './frontend/App.js'const __dirname = dirname(fileURLToPath(import.meta.url))const html = htm.bind(react.createElement)// (1)const template = ({ content }) => `<!DOCTYPE html><html><head><meta charset="UTF-8"><title>My library</title></head><body><div id="root">${content}</div><script type="text/javascript" src="/public/main.js"></script></body></html>`const server = fastify({ logger: true }) // (2)server.register(fastifyStatic, { // (3)root: resolve(__dirname, '..', 'public'),prefix: '/public/'})server.get('*', async (req, reply) => { // (4)const location = req.raw.originalUrl// (5)const serverApp = html`<${StaticRouter} location=${location}><${App}/></>`const content = reactServer.renderToString(serverApp) // (6)const responseHtml = template({ content })reply.code(200).type('text/html').send(responseHtml)})const port = Number.parseInt(process.env.PORT) || 3000 // (7)const address = process.env.ADDRESS || '127.0.0.1'server.listen(port, address, function (err) {if (err) {console.error(err)process.exit(1)}})
There’s a lot of code here, so let’s discuss the main concepts ...