React 3
  • Overview
  • Transcript

2.4 Server-Side Rendering

We're finally at the point where we can render our components on the server. The bulk of our code is already written, so we just need to write a few lines to make the magic happen!

2.4 Server-Side Rendering

In the previous lesson we finished the client portion of our application and that works and that's wonderful. But that's only half of our application. We also have the server that we want to implement as well. Although in our case the majority of the code is already written, so the server portion of our application is actually going to be about a quarter maybe a fifth or a sixth of the overall application. Because that's one of the wonderful things about Universal JavaScript applications. We can share code between both client and server. So, basically on the server, we want to do the equivalent of this, we want to render our routes but we aren't going to use AppRoutes because this uses the router component, if we go and look at Approutes. We have the router component and then we have our routes. Now we can use the router component on the server but we aren't going to see anything on the screen, and the reason is because server rendering is synchronous and route matching is asynchronous. So instead we're going to use a separate component for rendering our routes. So this means that if we want to reuse the routes that we have defined we need to break these routes out and place them inside of another file. So let's go ahead and do that, it's going to be inside of the routing folder I'm just going to call this routes. And we actually want to do quite a bit here, we wants to essentially imports everything that we were already importing and we also want to take out our routes. And inside of the new routes js, we are going to create a variable called routes and we are simply going to paste in those routes and of course we want to export routes. So exports default routes and we are good to go in that file. So let's go back to our app routes, we don't need the import statements for app, home and guitar because we aren't using those inside of this file anymore but we do need to import our routes. And I'm going to call that routes with a capital R just to Keep things well no that's really not capital is a class. So we'll import our routes from and this is the same folder and just routes. So, we don't need the routes component we don't need index route because we aren't using those here either. But we do need to add a property called routes to the router and we are going to specify that as routes and that's all that we need to do in this file now. So now that we have broken our routes out we can then use them on the server, so let's close this. Let's create a new file called server app. In hindsight, I should have just called it's client, but well. So I will say server app js, we want to imports react from react. And then we want to be able to render our component. So to do that we're going to use a function called rendertostring and that is from react.dom/server. Then we also need to import some things from React router, the first is a function called match which is what we are going to use to match the request URL with any of our routes. So match and then a component called a RouterContext. This is what we are going to use instead of the router component. So you can think of this as the server equivalent to the router component. And this is from React router, we also want to pull in our routes here, so let's say routes from and that is inside of components routing. And then routes and then of course we want Express. So let's add an import for that as well I'm going to put that at the top and that is from Express. So let's starts writing our code here, so the first thing we're going to do is create our app. We're going to new app Express and then let's go ahead and call the git method, now we are going to handle every request here and we're going to pass that on to the match function. So for our callback, we get the request and response, the first thing we will do is call match. We need to pass an object to the Match function. This is going to have two properties, the first is called routes so we are passing our routes there and then we want a location and the location is our request URL. So then we have a call back where we have an error. Now if there was any redirect going on, let's a redirect location and then if there was a match found we have our render props. So we need to do three things will really four things here. The first thing we need to do is check to see if we have an error and if we do then we are going to return a response with a status of five. 500 and send that error message. So that's the first thing we need to do. The second thing we need to do is check to see if we have redirect location. And if we do, then we are just going to pass that on to the server, well, we are on the sever. We're going to pass that back to Express, that's the technical thing that we are doing. So that Express will handle the redirect. So our status is going to be 302 and we need to take the redirect location. This has a property called path Name and we want to concatenate that with redirect location and the property is search. So that's the second thing that we need to do if we have an error. We let express return an error if we have a redirect, we let express do the redirect. But now if we have renderProps this is what we are here for. We want to render our route. So let's create a variable called HTML, this is where we are going to use our renderToString function and we are going to pass in a component our RouterContext and then to our RouterContext, we are going to pass in the render props, so that is going to render whatever it is that we just requested. And so, now that we have this rendered do we need to decide how we are going to get it back to the client. We could use a view and then pass the HTML to the view kind of like what we did with the index HTML file. I mean it's not exactly what we would do, but we could essentially take this and create a view so that we would display the rendered content inside of this div element and that is what we are going to do. But the whole point here is that once we have this rendered HTML, we can do whatever we want with it because it is now rendered. So, we don't have this view yet, and we haven't set up our views but this is what's we're gonna do. We're gonna call the render method, and then we want to render our view which let's just call this guitar page. And then for the data that we're going to pass to the view HTML. But if we make it pass render props then we essentially have a 404 so we can return res.status[404].send (Not Found) Now if we wanted to, we could render our not found component and then we could pass that on to the view as well. But to keep things simple, we're just going to rely upon express to handle that 404. So this code right here is the heart of the server. We are handling every request and passing that off to the reactor router. And then based upon whether or not the reactor router gets an error, a redirect, a match or nothing, then we do whatever is appropriate. So, now we just need to set up the view engine, we also need to set up the server itself. And I'm going to take the easy route and just use EJS for our view engines. So, we're going to say app set that the view engine Is going to be ejs. We also need to set up the path for our views. So our views are going to be, we don't have path, do we? So let's add path, import path from "path" and we want to use path.join. We will get the directory name, and a let's just call the folder views. That makes sense, but we also need to set up the static location as well. So express Static and will use path join once again the directory name and our static stuff is inside of public. So we have our views set up let's set up the server now. So let's start with the ports which is going to use data from the environment, first of all. But if we don't have a port then let's just pick 8080. That's what I have been using. And then we will listen for any requests on that port and hopefully we won't get an error but it's possible that we will. If error then we will return the console error and we will pass in the error. Otherwise, it wants to write to the console that we have a production express server running at local host and then our ports. So now let's add our views folder, this is going to be also inside of source. So new folder views and we want to create a new file, let's see. What is that? Guitar-page.ejs, and we are essentially going to take index.html and paste that into that new page, guitar-page.ejs. Now we do need to add where we want the HTML to go so we will do that right there. And we should be good to go. So now I'm going to open up package dot JSON and I'm going to change start. Instead of using HTTP server, I am going to say babel-node and our application is in server.app.js and we are going to use presets,react and es2015. Okay, this is the moment of truth, let's go to here and in PM starts. Hopefully this is going to start without any issues. I would be surprised if it does because I am horrible at typing. [LAUGH] Yes, okay, so the console in Windows 10 is a lot better than what it was. But well thankfully this is a rather easy error to find but If you're using just the plain command prompt things can get a little muddy, if you use PowerShell then everything is clear as day. So let's go back to the server app, this should be listen Instead of list. So let's try that again.So,we'll run the same command. Hopefully now everything will work and it does.So let's go and let's go to our home page. Now it's not clear right now. What is being loaded actually right now index HTML loaded this page and so if we navigate everything works like it should. But now we don't really want to use index HTML because that means that if we make any changes to our HTML file or to the view then we have to update both of those. So let's just rename index html to index.1.html just so that that's not going to be loaded anymore. Let's go back to browser refresh and wallah we have server rendering. Now if you want to be absolutely sure let's do this inside of our view lets just write something to the console in some script. So we will say console.log In view, that should be good enough, and then we will go back to the browser and refresh the page. We will check the console, actually lets open that first and refresh, we are in the view. So we are rendering our application on the server if we go to any of the pages, that works. If we go straight to one of the guitar pages, so guitar/1 then we go to that page. And so now we have a universal application, we are rendering both on the server and the client.

Back to the top