Deno First Look Serving Static Files in Oak
Transcript from the "Serving Static Files in Oak" Lesson
[00:00:30] And then let's add some CSS to this file, right. So now what we wanna do is we wanna reference this file from our template. So I'm gonna go to the template, to our layout template because we want this to apply to everything in the application. And I just wanna link to it.
[00:00:50] So let's just do link. And then let's go to public/stylesheets/site.css. Okay, now, we need some way to tell Oak, when it sees this public URL here, that it needs to serve up the file that's inside, right? We have to figure out how to tell Oak to serve up static resources or static assets, which is what we're gonna do now.
[00:01:18] So, to do that, we need to define very creatively a route to handle it. So we might do something like this. Let's go back to our app file. And we might define a route that says like this is static files route. And what we're doing here is just for saying anything that comes on public with PATH just serve up the value that's in the PATH variable.
[00:01:49] Because we know that PATH is gonna contain stylesheets/site.css. So we can do that, and the way that we would return our result here, we would just tell it to send back the static file, even though we haven't talked about how we're gonna do that yet. The problem is that this won't work, because PATH right here, is gonna be equal to in our case, it's gonna be equal to stylesheets, right?
[00:02:25] So sorry, it won't match the PATH. That's the problem. So path is gonna be stylesheets. It's gonna look like this /site.css. I don't know vs code keeps changing this for me. And the problem with that, is that it's only gonna pull, it won't match this URL because this doesn't match this.
[00:02:46] And so what we need to do is say like, match this PATH, and like everything that comes after it. So everything that comes after public should be considered the variable. And we do that by just adding a plus sign on the end. It's kind of like a wild card.
[00:03:02] And so it really won't match everything that comes after public slash anything will get matched here, which is what we want. Now we just need a way to send back the static file. So we go to our depths file here. There is a method not that file, this file.
[00:03:23] There's a method here called, if we look here, there's a function called send. Let's just use this thing, so we're gonna export it. Okay, and then in our app file, we wanna bring it in. And we want to send the file back and use it. So, down here what we wanna do is just send back the file.
[00:03:49] So we could say send, right? And then all we have to do is, pass in the context and then the PATH to the file. So we should be able to say ctx and I think its path is the variable here. Let me make just make sure I'm doing that right.
[00:04:08] Yeah, params that path, and it's a promise. So we need to await this. So we're gonna send in the context and then ctx.params.path. But typescript does not like this, because if we hover over it it says, argument of type string undefined is not assignable to parameter of type string.
[00:04:33] In other words, this could be undefined and that's not okay. So we have to give it like an alternative value here of empty string. Typed languages, y'all, that's just how it goes. All right, so with that, we should be able to send back that file now and display the CSS in our page.
[00:04:51] So let's go back here, refresh, and let's see what's happening in our outside. So we're getting a 404 file not found. Why is that happening? Well, let's see here. Right now, we're not seeing any errors in our application. If you look at the console, there's nothing in there, right?
[00:05:14] But there's an error happening, but we don't see it. And that's because Oak swallows errors for you unless you otherwise handle them. You just don't see him, but we can see them if we just tell Oak a little bit about how we wanna handle those errors. So let's do that.
[00:05:37] I'm just gonna say app.addeventlistener. And we're gonna look for the error event. And then on that we just wanna handle we're just gonna pass in the error and handle it. So we'll just log into the console. Like this. Okay, and now Restarting, now let us see if we can figure out what is happening here.
[00:06:06] Okay, so now we have got an error. What does it say? No such file or directory. So it doesn't know it can't find this file. So what we could do here, is we could just log and say like well, what is the value of path? Sorry, what is the value of ctx.params.path.
[00:06:33] This is one way to do it. Probably the simplest way to do it. And then refresh. And then we can scroll back up and it is stylesheets/site.css. Well, the problem is, it's in public/stylesheets/site.css. So what can we do about that? Well, one of the things that we could do is, use that current working directory to specify a root here.
[00:07:05] So on the send, we have an options object that we can use. So if I do this options, and then we can specify the root directory. And so our root directory would be Dino dot the current working directory, right? That's the path to the to the directory we're in now plus public.
[00:07:24] So let's just do it like this, let's use a string template literal to the current working directory slash public. All right, so that hopefully that will work. So let's go back to our app, refresh, we have a stylesheet, okay, because now we've got the correct path. There's actually a better way to do this.
[00:07:53] If we were to go in and do a little bit of debugging and digging around here instead of relying on the path parameter here rather, we can use ctx.params. So no sorry ctx.url, what is it? Sorry ctx.request.url.path name. And that is always a string. It's never undefined. And by doing that, we've made this code a little bit tighter.
[00:08:28] And because it's gonna have the path name, it's gonna include public. So we don't need this anymore either. So we could just say the root is, Deno.cwd(). And this should still work. Let's make sure we've restarted, there we go, refresh. And it does, all right? So just a simpler way to return that same, static file.