How to Serve Static Assets Using ExpressJS

Learn how to use ExpressJS’ built-in middleware function for serving static assets in this tutorial by Eddy Wilson Iriarte Koroliova, a senior full-stack developer and JavaScript specialist with the MERN stack.

What is MERN?

The MERN stack is a solution composed of four main components:

  • MongoDB: A database that uses a document-oriented data model
  • ExpressJS: A web application framework for building web applications and APIs
  • ReactJS: A declarative, component-based, and isomorphic JavaScript library for building user interfaces
  • js: A cross-platform JavaScript runtime environment built on Chrome’s V8 JavaScript engine that allows developers to build diverse tools, servers, and applications

These fundamental components that comprise the MERN stack are open source and are thus maintained and developed by a great community of developers. What ties these components together is a common language, JavaScript. In this tutorial, you will use ExpressJS to see how to build a web application that will serve static assets.

ExpressJS 4.x

ExpressJS 4.x and newer versions include only two built-in middleware functions. The first one is the built-in error handler middleware function. The second one is the express.static middleware function responsible for serving static assets.

The express.static middleware function is based on serve-static module (https://expressjs.com/en/resources/middleware/serve-static.html). The main difference between express.static and serve-static is that the latter one can be used outside ExpressJS.

Prior to the 4.x version of ExpressJS, the middleware functions used to depend on ConnectJS, which is an HTTP server framework (https://github.com/senchalabs/connect). In fact, most middleware written for ConnectJS are also supported in ExpressJS.

As for the 4.x version of ExpressJS, middleware functions no longer depend on ConnectJS, and all the previously built-in middleware functions have been moved to separate modules (https://expressjs.com/en/resources/middleware.html).

Using ExpressJS’ built-in middleware function for serving static assets

To get started, create a new package.json file with the following content:

{
"dependencies": {
"express": "4.16.3"
}
}

Then, install the dependencies by opening a terminal and running the following command:

npm  install 

How to do it?

  1. Create a new directory named public.
  2. Enter the new public
  3. Create a new file named html.
  4. Add the following code:
      <!DOCTYPE html> 
      <html lang="en"> 
      <head> 
          <meta charset="utf-8"> 
          <title>Simple Web Application</title> 
      </head> 
      <body> 
          <section role="application"> 
        <h1>Welcome Home!</h1> 
          </section> 
      </body> 
      </html> 
  1. Save the file.
  2. Navigate out of the public
  3. Create a new file named serve-static-assets.js.
  4. Add the following code and initialize a new ExpressJS application:
const express = require('express') 
const path = require('path') 
const app = express() 
  1. Include the express.static configurable middleware function and pass the path of the /public directory where the index.html file is located:
      const publicDir = path.join(__dirname, './public') 
      app.use('/', express.static(publicDir)) 
  1. Listen on port 1337 for new connections:
app.listen(1337,() => console.log('Web Server running on port 1337'),)
  1. Save the file.
  2. Open a terminal and run this code:
node serve-static-assets.js
  1. To see the result, navigate to the following link:
http://localhost:1337/index.html

How this works?

Your index.html file will be shown because you have specified “/” as the root directory for looking at assets.

Try changing the path from “/” to “/public”. Then, you will be able to see that the index.html file and other files that you want to include in the /public directory are accessible under http://localhost:1337/public/[fileName].

Suppose you have a big project that serves dozens of static files, including images, font files, and PDF documents (those about privacy and legal stuff) among others. You’ve decided that you want to keep them in separate files but don’t want to change the mount path or URI. They can be served under /public, for example, but they will exist in separate directories in your project directory:

Create a public directory that will contain a single file named index.html:

  1. Create a new directory named publicif you didn’t create it in the previous example.
  2. Enter the new public
  3. Create a new file named html.
  4. Add the following code:
      <!DOCTYPE html> 
      <html lang="en"> 
      <head> 
          <meta charset="utf-8"> 
          <title>Simple Web Application</title> 
      </head> 
      <body> 
           <section role="application"> 
           <h1>Welcome Home!</h1> 
           </section> 
      </body> 
      </html> 
  1. Save the file.

Now, create a second public directory that will contain another file named second.html:

  1. Exit the public
  2. Create a new directory named another-public.
  3. Enter the new another-public
  4. Create a new empty file named html.
  5. Add the following code:
      <!DOCTYPE html> 
      <html lang="en"> 
      <head> 
          <meta charset="utf-8"> 
          <title>Simple Web Application</title> 
      </head> 
     <body> 
          <section role="application"> 
           Welcome to Second Page! 
          </section> 
     </body> 
      </html> 
  1. Save the file.

As you can see, both files exist in different directories. Follow these steps to serve those files under one mount point:

  1. Exit the another-public
  2. Create a new file named router-serve-static.js.
  3. Include the ExpressJS and path libraries. Then, initialize a new ExpressJS application:
const express = require('express') 
      const path = require('path') 
      const app = express() 
  1. Define a router:
const staticRouter = express.Router() 
  1. Use the express.static configurable middleware function to include both public and another-public:
      const assets = { 
           first: path.join(__dirname, './public'), 
          second: path.join(__dirname, './another-public') 
      } 
       staticRouter 
          .use(express.static(assets.first)) 
          .use(express.static(assets.second)) 
  1. Mount the Router to the “/” path:
app.use('/', staticRouter) 
  1. Listen on port 1337 for new connections:
app.listen(1337, () => console.log('Web Server running on port 1337'),)
  1. Save the file.
  2. Open a terminal and run this code:
node router-serve-static.js
  1. To see the result, navigate to the following link:
http://localhost:1337/index.html
http://localhost:1337/second.html
  1. Two different files in different locations have now been served under one path. However, note that if two or more files with the same name exist under different directories, only the first one found will be displayed on the client-side.

If you found this article helpful, you can explore Eddy Wilson Iriarte Koroliova’s MERN Quick Start Guide. This book gives practical and clear hands-on experience that can help you get started, learn, understand, and build full-stack MERN web applications.

Leave A Reply