Complete 2024 Web Development Bootcamp

Dr. Angela Yu

Back to Express Index


Express Server Setup
Intro

We're going to discuss here how to set up an express server but first we should talk about what that is. An express server is a JavaScript/Express file that resides in the root directory of the project's CWD. It is set up to process requests from a client terminal. This means we need a JavaScript file running on the server, (eg. index.js), with Express installed through the npm process.

Download all of the server project files: expressServer.zip.

You can access the "served" index.html file that we will create here @ localhost:3000, but remember, our server must be up and running to retrieve this file. We will discuss how to do this, here.

So how do actually create this Express server setup? Good question. The process has seven (7) basic steps:

  1. Create a working directory (CWD)
  2. Set up the directory structure
  3. Create an index/js file
  4. Initialize our npm structure (npm init)
  5. Install the Express package (npm i express)
  6. Write the Server application code in index.js
  7. Start the server (run nodemon index.js)

Directory Structure

So the first thing we need to do is to set up our working directory. This is going to start with a root directory. In this example, we'll call our root directory "project". We also need to create a public directory.

What is a "public" directory? Well, I'm glad you asked.

In a Node.js application, particularly when using Express, the public directory is a folder that contains static files such as HTML, CSS, JavaScript, images, and other assets that are served directly to the client without being processed by the server. This directory is typically configured to be accessible via the web server, allowing clients to request and receive these files directly.

So what happens once this is all configured properly, is that when a client terminal requests a webpage from the server, the server sends that page back to the client, along with all of the required static files that the page requires. So the server file is going to need to know where our "public" directory is, as it contains all of our static files.

This is all configured in the server setup and we'll get to that shortly, but for now we need to get our basic working directory set up (including a public directory). It will look something like this:

  • project
    • Folder Icon  public
      • Folder Icon  css
      • Folder Icon  images
      • Folder Icon  scripts
      • HTML Icon  index.html
    • Javascript Icon  index.js

This will take care of steps 1 thru 3 above.

  1. We created our CWD: "project"
  2. Our directory structure is set up, complete with the public directory and its appropriate sub-directories.
    • (remember that this public directory is where all of our "static" files will be "served" from)
    • (also, the sub-directories are optional as you may not need any of these, or you may have others that you do need)
  3. We created a index.html file which essentially becomes our website "home page", getting served from the server.
    • (notice that this goes in the public directory as it is one of our necessary "static" files)
  4. We created our index.js file which will eventually become our server file. For now it is an empty file.

npm init

The next thing we need to do is run npm init to set up our package.json file. Once this is accomplished we will run [ npm -i packageName ] to install any npm packages that we need for our project. This will create our node_modules directory, and update our package.json file with the needed dependencies.

When we are finished, our directory structure will look something like this:

  • project
    • Folder Icon  node_modules
      • (any npm installed packages will be here)
    • Folder Icon  public
      • Folder Icon  css
      • Folder Icon  images
      • Folder Icon  scripts
      • HTML Icon  index.html
    • Javascript Icon  index.js
    • json Icon  package-lock.json
    • json Icon  package.json

and our package.json file will look something like this:

  • {
    • "name": "projectName",
    • "version": "1.0.0",
    • "description": "projectDescription",
    • "keywords": [any, keywords],
    • "author": "authorName",
    • "license": "ISC",
    • "main": "index.js",
    • "type": "module", // either [commonjs] or [module]
    • "scripts": {
      • "test": "echo \"Error: no test specified\" && exit 1"
    • },
    • "dependencies": {
      • any dependencies (from npm packages) are listed here
    • }
  • }

This will take care of steps 4 and 5 from above.

Most of this data is assigned during the npn init process, unless you specify the npm init -y option which skips all the questions asked during the init process and just accepts default values. You can always edit this file and enter the values manually.

Notice that main is pointing to index.js. This will be your "main" Js file for the project, (usually your "server" file). Also notice the type definition here. This defines how you are going to import packages into your Js file:

  • commonjs: uses require for importing files - older method
  • module: uses import for importing files - newer method

This must be defined here, or your imports will not work properly.


Server Code

This should get us to step 6, which is actually building the index.js server code. We're going to go ahead and document the code, then we will break it all down.

  • JavaScript
  • Server File
  • // import the express object from the express module
  • import express from 'express';
  •  
  • // dynamically build a path to the ROOT directory
  • // import the dirname function from the path module
  • import { dirname } from 'path';
  • // import the fileURLToPath function from the url module
  • import { fileURLToPath } from 'url';
  • // define the root path
  • const __dirname = dirname(fileURLToPath(import.meta.url));
  •  
  • // assign variables for the express function & port #
  • const app = express();
  • const port = process.env.PORT || 3000;
  •  
  • // set a default directory for static assets (the "public" directory)
  • app.use(express.static("public"));
  •  
  • // get request for home page (public/index.html)
  • app.get( "/", ( req, res ) => res.sendFile( __dirname + "index.html") );
  •  
  • // start the server & enter "listening" mode
  • app.listen( port, console.log(`Server running on port: ${port}` ) );


and let's break this all down, one line at a time:

  • import express from "express"
    • - imports the express object from the express.js framework
    • - gives us the Express.js functionality in our application

  • const app = express();
    • - this assigns the express function to a variable to make the coding simpler

  • const port = process.env.PORT || 3000;
    • - we set our port number to a variable so that if we ever want to change our port assignment we only have to change it in one place
    • - this code is checking to see if a port has already assigned. if not, use port 3000

  • - dynamically build a path to the ROOT directory
  • import { dirname } from 'path';
    • - import the dirname function from the path module
    • - used to get the directory name of a given file path
    • - used to define our root directory for our app

  • import { fileURLToPath } from 'url';
    • - import the fileURLToPath function from the url module
    • - this function converts a file URL to a local file system path
    • - used to define our root directory for our app

  • const __dirname = dirname(fileURLToPath(import.meta.url));
    • - this is going to combine the dirname and the fileURLToPath with the imported meta.url to give us a valid path to the root directory of our project.
    • - we then take this path and assign it to the variable __dirname so that anytime we call __dirname, we are indicating a path to the root directory of our project.
    • - So if we call [ __dirname + "/index.html" ], we are saying root/index.html.

  • - define our public directory
  • app.use(express.static("public"));
    • - express.static is a "middleware" function of express.js. in this instance, it is telling the app to use "root/public" as the static files directory.
    • - this directory is where we build all of our relevant "static" files and folders (css, images, scripts, etc.)

  • - send a "get" request
  • app.get( "/", ( req, res ) => res.sendFile( __dirname + "index.html") );
    • - we are sending a get request for a file at the root directory (/)
    • - because we have a "static" directory defined as root/public, any request for (/) will point to the root/public directory
      • - we are "sending" the file "index.html" that resides at the root of the "public" directory

  • - set the server to "listen" for requests
  • app.listen( port, console.log(`Server running on port: ${port}` ) );
    • - this puts the server in "listening" mode to "listen" for server requests.
    • - it also sends a message to the console that the server is actually up and running

So this will complete our Step 6 in the process. All that is left is step 7: Start the server.


Starting & Stopping the Server

To actually "start" our server, we open up our Terminal of choice, navigate to our project's root directory, and enter nodemon index.js. Once the server is up and running we will see a console.log stating "The server is running and listening on port: 3000"

Now that our server is up and running, we can access the server output (our requested page), in our browser by entering http://localhost:3000 into the browser address bar.

Why are we're using "nodemon" instead of "node"?

Well, whether you use "node" or "nodemon" depends on where you are in the development process. While we are building and developing our project, we use "nodemon" because it stops and restarts our server when we make changes to the file structure. But if we are just "running" our server, we would probably just use "node".

And finally, now that our server is up and running, how do we shut it down? Once again, from the Terminal of choice,

  • press ctrl - c
and the index.js file that we are running, will terminate shutting down our server.


One last tidbit:

While we're talking about ports, if you open a Terminal, and enter the command:

  • netstat -ano | findstr "LISTENING"
you will actually get a list of all of the ports that are open and "Listening" on your computer.


Back to Top