Check out a free preview of the full Complete Intro to React, v3 (feat. Redux, Router & Flow) course:
The "Implementing Server-Side Rendering" Lesson is part of the full, Complete Intro to React, v3 (feat. Redux, Router & Flow) course featured in this preview video. Here's what you'd learn in this lesson:

To compile the server-side code to CommonJS modules, Brian updates the .babelrc configuration file and then adds the server logic. Brian introduces Express and implements the server-side rendering of the application.

Get Unlimited Access Now

Transcript from the "Implementing Server-Side Rendering" Lesson

[00:00:00]
>> Brian Holt: The next thing I'm gonna need you to do is open .babel.rc.
>> Brian Holt: If you remember, we're using import everywhere, the ES6 module system in Node. We're gonna have to translate that so Node knows how to understand it because Node still does not know how to do ES6 modules, right.

[00:00:19] So we´re gonna have to give it another env here and it´s gonna actually be the same as test. That´s not always gonna be the case, it´s probably often gonna be the case, but we´re gonna make another one called server,
>> Brian Holt: That's gonna have plugins,
>> Brian Holt: And it's gonna have the same transform-es2015-modules-commonjs.

[00:00:49]
>> Brian Holt: Again, you could make these the same env.
>> Brian Holt: They're different concerns, right? What goes into test is not necessarily gonna be what goes into the server but,
>> Brian Holt: So I recommend against doing that, despite the fact that it'd be impossible, okay? So,
>> Brian Holt: From here I want you to create a new file, it's going to be called server.js.

[00:01:14] It's going to be outside of the JS directory cuz everything in the JS directory is our React app. This is going to be in the top level, this is going to be our node server.
>> Brian Holt: And this is just gonna be a lot of code all at once because you need all of it for it to work, so just bear with me.

[00:01:34] First thing I'm gonna do is I'm gonna use some console logging in here and that's okay. So no-console: 0, this is turning off the no console warning for this particular file. First thing we're gonna do up here is require babel-register.
>> Brian Holt: There's a couple ways you can do this.

[00:01:58] I'm using babel-register, which means everything in this file itself will not be transpiled, so I can't use JSX or anything that Node doesn't understand here. But everything that it requires will be run through Babel. So when I require my app, it can use jsx, it can use es, like future es stuff.

[00:02:17] All that's fine and that's what babel-register does for you. It's kind of hooking into that require and running in all through Babel. There's another thing called babel-node that will actually compile the file that's being run as well and you're welcome to use that. It's kind of up to you.

[00:02:34]
>> Brian Holt: So let's just require a bunch of stuff now. So const express = require('express').
>> Brian Holt: const React = require ('react').
>> Brian Holt: const ReactDOMServer,
>> Brian Holt: = require ('react-dom/server'). const ReactRouter = require (react-router-dom'). const _ = require ('lodash'). Const fs = require ('fs'). And const App = require ('./js/app'). And something you're going to have to do here.

[00:03:40] If you recall we're using ES6 modules, so when that get's translated to being a required common js module, remember we export default, right? So you're going to have to say .default, that's just what you have to do there.
>> Brian Holt: Cuz this is going to return to an object with one key in it and the one key in it is going to be default.

[00:04:02] And hence you have pull the default part off of it. Okay, from here we're gonna pull out const StaticRouter = ReactRouter.StaticRouter.
>> Brian Holt: This StaticRouter is going to be what we're going to use to replace BrowserRouter. This works in Node. Okay, const port, you can put this in whatever port suits you.

[00:04:36] I'm gonna put it on 8080.
>> Brian Holt: const baseTemplate, this is going to be our index.html file. It is going to be equal to fs.readFileSync(' ./index.html').
>> Brian Holt: So just so you're aware, this is definitely not a Node course, but readFileSync is going to read this file from the file system.

[00:05:11] And it's going to pause until it is finished reading. This is typically a horrible idea, however, on startup it's okay, right, cuz this is going to be read once. If you're doing readFileSync at every request you're gonna have a bad time for sure, so just be aware. Typically you would do here is readFile, right, and then you would provide it a callback once it was finished reading it.

[00:05:34] But here we can do sync, since this is gonna be done once on startup, and that's totally fine.
>> Brian Holt: const template = _.template(baseTemplate). What template is going to be now is a function that when we invoke it, we pass in body and we're going to get back our markup inside of the index.html file.

[00:06:02] So this is a function.
>> Brian Holt: Okay, that should be enough kind of set up for ourselves. And now we're gonna say const server = express(). Again, you can do this with any different Node server. We could use Restify, we could use Happy, we could use Kula. I am just using Express because it's very simple and it suits our needs for today.

[00:06:34] And the first thing we´re gonna do here is say server.use('/public', express.static ('./public')). This is just saying statically serve everything that's in the public directory. So that's all our CSS, that'll be our bundle.js, that will be all that stuff, all the images. It'll also put all the correct mime types and all that kind of stuff for us because that's really annoying to write yourself.

[00:07:08] Okay and then after that we're gonna say server.use((rec, res) ). This is where we're going to be doing our templating and all that kind of stuff.
>> Brian Holt: So I'll pull this up so you can see it. So the first thing we're gonna wanna do is create a context object.

[00:07:33]
>> Brian Holt: This is something that's going to be passed to ReactRouter.
>> Brian Holt: Gonna say const body = ReactDOMServer.renderToString. So you know how we use ReactDOM.render and then we tell it where to put it in the DOM, right? This is replacing that, instead of rendering out to as a DOM or something like that, it's just going to give you back a string of the html, okay.

[00:08:03]
>> Brian Holt: Then here, remember that we're not in jsx land, so we can't use jsx here. So we're going to fall back to that first set of skills that I taught you, very first thing, of using React.createElement.
>> Brian Holt: So this should all look familiar to you. So React.createElement,
>> Brian Holt: And the first most outermost layer is going to be the StaticRouter.

[00:08:31] And we're going to pass to the StaticRouter the location, which is going to be rec.url, right? That's what the user requested from the website. And we're going to pass to it the context object, but if you remember context: context, we can shorten that down to just context. But that's what that is, context: context.

[00:08:55] And then inside of that, we're gonna have React.createElement(App). And we don't need to give anything to App, that's just fine, right? So it's gonna be a StaticRouter on the outside, and App on the inside, and that's all that's gonna be. Okay, so now we're gonna get the string which is gonna be here on body, right?

[00:09:21]
>> Brian Holt: So the reason why we passed in this context objects to ReactRouter is sometimes you're gonna get redirected, right? Our app will never redirect, because we never wrote any redirects, right? But if that happens, I wanted to show you how that you would handle that. Oops.
>> Brian Holt: So you're gonna say if(context.url), so this is gonna say, ReactRouter is going to modify this context object that you pass into it.

[00:09:50] If there's a redirect in here you can say, res.redirect.
>> Brian Holt: And you can put the status on here if you want to, like 301 or 302 depending on what you're doing. I'm just gonna leave it off for now. (context.url), I think it defaults to 301 if I remember correctly.

[00:10:11] So that's how you do that. If there is a redirect, this will send them off to wherever they need to go. Otherwise res.write(template({body: body}), but again we can just put {body}.
>> Brian Holt: And then you're gonna say res.end.
>> Brian Holt: So this is server-side rendering with ReactRouter. What's amazing about this is we don't have to duplicate our logic anymore, right?

[00:10:49] We get to write one set of route definitions in the client and it's automatically sent to Node as well. So you have one source of truth.
>> Brian Holt: Okay, down here at the bottom we're gonna say console.log('listening on ${port}') to let it see into the console that we're up and going.

[00:11:19] And then we're gonna say server.listen(port).
>> Brian Holt: If you want to, you can say up here, console.log. Something I like to do is (req.url) so I can see requests coming in and where they're going. And typically, you would have some sort of like server logging framework like Morgan or something like that.

[00:11:45]
>> Brian Holt: There's plenty of great Node stuff on Frontend Masters. So if that's interesting to you, go down that path.