Check out a free preview of the full Complete Introduction to React (feat. Redux and React Router) course:
The "Browser vs. Server Rendering" Lesson is part of the full, Complete Introduction to React (feat. Redux and React Router) course featured in this preview video. Here's what you'd learn in this lesson:

Since universal rendering involves the server sending a fully-rendered version of the application, there can’t be any reference to browser APIs. Brian creates a separate module that will act as the browser’s entry point in the application.

Get Unlimited Access Now

Transcript from the "Browser vs. Server Rendering" Lesson

[00:00:00]
>> [MUSIC]

[00:00:03]
>> Brian Holt: Now we've got our app into a good state that we can get it to universally render nicely. What we need to do now is fix client app just a tiny bit. Reason being is that document doesn't exist on the server, right? So if you tried to run this right now on the server, it's gonna say what the hell's document.

[00:00:24] Right. So what we have to do is we have to split out our app and actually what renders the app, right? So right now we've mashed two concerns together, which is creating our app and our router and our provider and all that kind of stuff. So, we have that and we also have actually putting it on the DOM.

[00:00:44] So we need to split those two concerns so that the app could be rendered on the server and then you can send down the renderer for the DOM only on the browser. So basically, we only want this part to work on the DOM. So that's what we’re gonna do right now.

[00:00:58] Create a new file called Browser Entry.jsx and this is gonna be a really short file. I'm gonna say const React=require(‘react’), const ReactDOM=require-dom and const App = require./ClientApp. And then ReactDOM.render<App> and documents.getElementById (app), okay? That's it. That's all we need to do in browser entry. So we've just externalized this concern that we were worried about.

[00:01:56] And now we just have to go fix client app to get it.
>> Brian Holt: So go back to current app, get rid of the line down here, this ReactDOM and replace it with module.exports = App, right? Cuz now this is no longer the entry to the R app, this is just another export.

[00:02:22]
>> Brian Holt: So let's save that. We also have to go fix our web pack config, so go to web pack config and come in here to. This isn't gonna be client app anymore. That's no longer the entry to our program. It's gonna be browser entry. So save that, and you can actually go test to make sure everything still works.

[00:02:45] I didn't get rid of that. So, go back to a client app.jsx and get rid of ReactDom up here as well. Right, cuz it's no longer being used here, it's being used in browser entry as it should be. So I'll save that, looks like we're bundling okay again.

[00:03:08]
>> Brian Holt: And refresh, just to make sure everything's still working as we expect. It's not, that's cool. Am I still running my server? I am.
>> Brian Holt: You know what it is? Stop and start your webpack again. Cuz we changed our webpack config, and it no longer knew which file was the entry.

[00:03:42]
>> Brian Holt: Okay, so our app should still work.
>> Brian Holt: Let's cut a branch really quick. So, anyone have questions while I'm cutting a branch?
>> Brian Holt: Awesome.
>> Speaker 2: One question was why did we separate out the browser entry from the app?
>> Brian Holt: It'll be apparent in just a second, but the basic gist is that we can't refer to document at all in the node environment.

[00:04:36] So we're about to write a note server that's going to bring in ClientApp and render it. And if we talk about document at all in the node environment, it crashes the whole server. That's the basic idea. So we have to separate what is our app from what is rendering our app to the DOM, cuz this code is only run in the DOM.

[00:04:56] So anything you only want done in the DOM goes into this file. When I say in the DOM, I mean in the browser, after it's been sent down to the client.
>> Brian Holt: Okay, any more?
>> Brian Holt: Okay, we're gonna do one more thing. Go to clientapp.jsx, we're filing the switch from hash history to browser history.

[00:05:31] Because we're gonna be moving to using react for our router. We actually have to use a browser history or it's not gonna work the way we anticipate it. So we have browser history here and then here on router, we're also gonna pass in browser history. Go and save that.

[00:05:49] Now your apps actually, well, it actually might still work on the initial page load. We're at the shop, refresh, browser. So, now it looks like it says search and Orange is the New Black and all that stuff. So it actually looks much nicer in our URL bar. But if I'm on details and I refresh, it's probably gonna break.

[00:06:11] It does break. Reason being is our HTTP server doesn't know how to handle that. It has no concept of routing. So we actually have to go make our own node server that is aware of the routing. So this'll only work on the homepage, and it'll work everything after that.

[00:06:26] But as soon as you refresh the page, it breaks.
>> Brian Holt: Okay, I updated webpack config.
>> Brian Holt: We have to also externalize our routes. Yep, that's one thing we have to do. So go back to ClientApp.jsx.
>> Brian Holt: So we basically need to move these routes out into their own thing because we have to be able to pass our routes individually into our router so that it knows how to do routing on the server.

[00:06:56] So do const myRoutes = (props), basically gonna make them a stateless functional component.
>> Brian Holt: Okay, so cut all that and just put it up here. Okay, and then here, we're just going to put those, so we're gonna say myRoutes.
>> Brian Holt: Right, nothing too fancy here. We just made our myRoutes up here and then we're just instantiating right there.

[00:07:50] This isn't really a real react component. It's just a function that returns a set of routes. So just an FYI, that's what's happening here. Okay, and now we need to export that, so we're gonna say, App.Routes = myRoutes, because now we need to be able to import this into node as well.

[00:08:13] So basically all the stuff that we're doing, we're making our app a little bit more ugly but we're kind of getting it ready to render on the server.
>> Brian Holt: And actually we don't use props anywhere here so you can just actually omit that if you want to, it doesn't matter.

[00:08:39]
>> Speaker 3: Is app.routes pre-defined or are we defining that here [INAUDIBLE]?
>> Brian Holt: Say that one more time.
>> Speaker 3: On line 30, when we were defining app.routes, are we defining that, just, it could be made anything?
>> Brian Holt: It could be named anything. Yeah, as long as you're aware of what's called.

[00:08:57] I just because we don't need this on enter here, I don't know why it's still there. Do we? We don't. It's not even a thing anymore.
>> Brian Holt: Okay, so move to index.html. Sorry, this is a lot of work for an eventual big payoff, right? There's no intermediary steps.

[00:09:22] It's either not running on the server or it is. And there's no in between. Okay. So, we're gonna use underscore templating cuz it's just really fast and really easy. So, if you've never seen this before, this just based, nope, I got that wrong. It's not equals, it's percent.

[00:09:41] This is an underscore templating tag. There's a million ways you can do this. I simply choose to do it this way because I find it very easy to do. So eventually, we're gonna render a string of our app and we're just gonna dumbly template it into there, right?

[00:09:57] So this indexation now has gone from being like a real HTML document to now it's actually just a template that we're gonna use. So anyway, what I mean to say is all of our react code is about to be just blurbed in there.