How to Load Static Files in Express

We created a blog application in the previous lesson, where the user can create, view, edit, and delete posts. However, we neglected a tiny detail. Notice that even though we successfully uploaded an image, it is not rendered in the views/post/show.pug template.

pug
1extends ../layout.pug
2
3block meta
4    title #{post.title}
5
6block content
7    h1 #{post.title}
8    div #{post.content}
9
10    a(href=`/posts/edit/${post.id}`) Edit this post

So, how can we add uploaded images in this case? It sounds like a simple task, but if you simply add a <img> tag and pass the image source like this:

pug
1img(src=`/${post.picture}`, alt="An image")

It will not work.

This is due to security reasons. Because by default, the users are not allowed to access the server's file system directly in the frontend, or any random user will be able to see the source code.

Loading images

However, there are some exceptions. For example, in this case, you need to allow the user to access the uploads directory in order to retrieve the images.

To do this, you must add the express.static() middleware.

index.js

javascript
1app.use("/uploads", express.static("uploads"));

Here we are using the same use() method we've seen before, except this time, you need to specify a route prefix (/uploads).

It is similar to how we define routes in Express, only instead of mapping to a controller, when Express encounters routes that start with /uploads, it will look for its target inside the uploads directory. For example,

pug
1img(src=`/${post.picture}`, alt="An image")

This will be rendered into:

html
1<img src="/uploads/1713217437399-cat.png" alt="An image" />

And notice that the src points to a route, which starts with /uploads, so Express will go to the uploads directory, and look for file 1713217437399-cat.png.

Loading scripts and CSS files

The files that are hosted on the server, but can be served directly to the user are called static files. The uploaded images are the most common kind of static files.

Besides the images, you can also serve CSS and JavaScript files (the kind that runs in the frontend) in a similar way. For example, assuming you have a statics directory like this:

text
1.
2├── controllers
3├── database.sqlite
4├── index.js
5├── libs
6├── models
7├── package-lock.json
8├── package.json
9├── routes
10├── statics  <===
11│   ├── css
12│   │   └── app.css
13│   └── js
14│       └── app.js
15├── uploads
16└── views

Add another middleware in our index.js.

index.js

javascript
1app.use("/statics", express.static("statics"));

And then, you can load the CSS and JavaScript inside the template like this:

views/layout.pug

pug
1doctype html
2html
3    head
4        block meta
5        link(rel="stylesheet", href="/statics/css/app.css")
6
7    body
8        nav
9            a(href="/posts/new") New Post
10            a(href="/") Home
11        block content
12        footer
13        script(src="/statics/js/app.js")

This technique allows us to modulate the frontend code.

Recall that in our previous examples, we put the Pug template and the JavaScript code in the same file, but now, you can put the JavaScript code in a separate file, and then import it into the template.