Build a Fullstack App with Vanilla JS and Go

Handling Nested Routes

Maximiliano Firtman
Independent Consultant
Build a Fullstack App with Vanilla JS and Go

Lesson Description

The "Handling Nested Routes" Lesson is part of the full, Build a Fullstack App with Vanilla JS and Go course featured in this preview video. Here's what you'd learn in this lesson:

Maximiliano discusses the issue of receiving 404 errors when refreshing or bookmarking specific URLs in a web application due to client-side routing not being recognized by the server. He demonstrates how to handle this by creating a catch-all client routes handler in the server-side code to deliver the index HTML for all client-side routes.

Preview
Close

Transcript from the "Handling Nested Routes" Lesson

[00:00:00]
>> Maximiliano Firtman: So right now we have our router actually working. So we can get into new pages, we can go back, we can go to even a page that doesn't exist yet, but we have a problem. For example, if I'm watching a movie, and if I refresh, I'm getting a 404, which is a problem for us while we are coding our app.

[00:00:23]
Because it means that we need to go all the time to the home page. But it's also a problem for users, because maybe the user is reloading, maybe the user is not reloading. But, for example, on mobile devices, when you get out of the browser, you come back later, sometimes the browser got out of the memory and it's going to reload the content.

[00:00:46]
And then the user will see a 404, and the same happens if the user is bookmarking that URL. So even if I'm seeing something, the Interstellar, and I wanna bookmark this, I can bookmark this, but then when I use the bookmark, it will give me 404. So it's wrong, okay, so something's wrong.

[00:01:06]
By the way, why I'm getting 404? Question for you.
>> Student 1: It's not a server route?
>> Maximiliano Firtman: Because?
>> Student 1: It's not a server route.
>> Maximiliano Firtman: Because it's not a server route. So when we refresh, also, if I copy and paste this URL in a new tab, this is creating a new navigation to the server.

[00:01:26]
And the server doesn't react to those URLs. So let's solve that, because we cannot publish an app in this state. So now we are going back to the backend. And I will go to main.go, remember, in main.go, we have all our handlers for every URL. So something that we are going to do is, before the FileServer handler, before the FileServer handler, because if you do that after, it's not gonna work, the file server handler should be the last fallback, we're going to say something like this.

[00:02:13]
I'm going to refactor this while I'm typing, so I'm going to say HandleFunct, for example, /movies, I wanna do something when the user, from the server, or to the server, is requesting /movies. So I need to create a handler. The thing is that, that handler will also be needed for other URLs.

[00:02:38]
For example, maybe to movies/ something else, or maybe account. We don't have that yet, but maybe in the future, we'll have an account section. So all the routes that we are creating client-side, should be defined here server-side. I'm gonna use the same handler, so I'm going to create the handler that I can reuse, okay?

[00:03:02]
This handler will be, actually, we can call this catchAllHandler, or catchAllClientRoutesHandler, however you wanna call this, okay? It's gonna be a function that follows the Handler pattern. So we receive w as http.ResponseWriter, and then we'll receive r, that is typically a request by, in this case, a pointer to Request.

[00:03:33]
And the next question is what to do with this. First, I will copy this, and I will paste this on these three places, okay? But what do you think, what should I do if the user is requesting that URL server-side? We're not doing server-side rendering, okay, so we are not rendering the movie here.

[00:03:56]
But where are the options? What do you think? So if the user is requesting /movies, what should the server do? There are two options. Option 1, make an HTTP redirect, that's 301 or 302, it depends on which one do you wanna use. Option 2, deliver the index.html, so let's analyze both.

[00:04:27]
The first one is probably the one that we are initially more pushed to actually implement, but it's not the right one. So if I make a redirect, what will happen is that the user will go to /movies, and then the server will redirect me to /, to the home page.

[00:04:50]
At least I won't get the 404, but I won't get the movies page, I will get the home page. Maybe it's better than 404, but it's still not the right solution, okay? So the right solution is to deliver the index.html, on some server-side platforms, not Go, it's called forwarding.

[00:05:11]
So it's not a redirect, it's a forward, it's kind of a solution from a server. We are not sending any instructions to the client, actually, we are going to serve one particular file here. We're going to actually say that I wanna serve one file to that writer, to that response writer, with that request, and we're going to serve public/index.html.

[00:05:36]
So not matter which URL we are getting in the server of this, at least those three groups. And by the way, server-side, this is actually a prefix. So everything that's starting with movies, will actually go to this ClientRoutesHandler, it's going to answer with the HTML, okay? Let's see this in action and see that there are more things that we need to do now.

[00:06:07]
So if I refresh now on /movies, so let's say /movies/14, okay, there was Men in Black, I think, so if I do this, I'm getting this. So I'm getting something, not the 404, I'm getting the index.html, but it's not working, does anyone know why? Also, if I look at the console, I may see some errors, and also on the Network tab, if I reload, I will probably see a lot of errors.

[00:06:40]
Now, actually not an error, but the styles.css file is giving me an HTML, app.js is giving me an HTML. So something's kind of wrong, right? Also, if I'm going to the root, the root is working, okay, so the root is working. The problem is this URL. Does anyone know what's going on?

[00:07:07]
Why is that styles.css is giving me an HTML? Let me give you a hint. If I open this in a new tab, this is just the CSS, there is a hint there of what's going on. The URL, styles.css is trying to grip that from movies.
>> Student 2: The server is returning the HTML for any URL that's-

[00:07:32]
>> Maximiliano Firtman: Any URL starting with movies, including the CSS, which leads to another problem, style.css is not inside movies. So when we are doing single page application and we are doing this trick of redirecting or forwarding everything from the server to index.html, we need to go to index.html and change every reference to an absolute reference.

[00:08:02]
So /styles.css, /app.webmanifest, /images/icon, /app.js, maybe the logo as well, and I think that's the last resource that I have. Also, we should change the base, and I'll show you if you have used that base,
>> Maximiliano Firtman: HTML element, it's been with us since the 90s. That base will actually define the base for every link that you have.

[00:08:31]
When you have a link that is relative, is not the case here because it start with /, but if it's doesn't start with /, it will use that base as a prefix. Okay, that's makes sense? So now when I'm going back here and I'm checking movies/14, if I refresh, I'm getting the right URL.

[00:08:56]
So I refresh, I'm getting the right URL. Now we can even change the URL with any other number, it works. So what's going on here? So we go to that URL to the server, the server doesn't know it's Kung Fu Panda, but the server says, it's start with movies, let's send the index.html.

[00:09:18]
When the index.html starts, we start the app, the app is initializing the router. And the router verifies that you already, says, you don't want a home, you don't want that particular movie. So it goes and renders the right component. Does it make sense? And now if I go and click on movies, so this is the real URL, so the current navigation has a real URL, this is the real URL.

[00:09:45]
But now if I go to movies, it's /, so we can still fake the URL, even if we are not starting from the /.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now