Start an Express Server

Get started with setting up and running a server.


In the last article, we installed Express and configured a gitignore file. This time around, let's write the boilerplate server code and start the server. I've posted some additional resources in the "Going further" section if you'd like to go into more depth.

Create server

Open VS Code and the integrated Terminal

View > Terminal

Next, enter the following to create a server JavaScript file.

touch server.js

Let's start building our server based on the Express documentation.

Add the following code to server.js.

const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => res.send('Express server running'));

app.listen(port, () => console.log(`Listening on port ${port}`));

The app responds with "Express server running" for requests to the root URL (/) or route. For every other path, it will respond with a 404 Not Found.

Start the server

The usual way to run a Node.js program is to run the node command and pass the file's name you want to execute.

To run the server type node server.js.

You can visit http://localhost:3000 in a web browser to see the message, "Express server running."

"Listening on port 3000" appears in the Terminal.

To exit use: Control ⌃C (control + c)

Of course, starting and stopping the server every time you make a change is tedious. So it would be nice to automate the restart, and that's what nodemon does.


In the previous article, we installed nodemon as a developer dependency. Unless you install nodemon globally, the following command results in an error.

nodemon server.js


zsh: command not found: nodemon

So, we can either install nodemon globally or use the NPX command instead.


"For the past couple of years, the npm ecosystem has been moving more and more towards installing tools as project-local devDependencies, instead of requiring users to install them globally."

"npx lets you run code built with Node.js and published through the npm registry."

"Node.js developers used to publish most of the executable commands as global packages, in order for them to be in the path and executable immediately."

"This was a pain because you could not really install different versions of the same command."

"Running npx commandname automatically finds the correct reference of the command inside the node_modules folder of a project, without needing to know the exact path, and without requiring the package to be installed globally and in the user's path."

In the Terminal, try the following.

npx nodemon server.js


[nodemon] 2.0.12
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node server.js`
Listening on port 3000

To exit use: Control ⌃C (control + c)

NPM scripts

We can define a shortcut command for starting the server using NPM scripts.

What happens if you run the command npm start or npm run start?


> backend@1.0.0 start
> node server.js

Listening on port 3000

To exit use: Control ⌃C (control + c)

"If there is a server.js file in the root of your package, then npm will default the start command to node server.js."

"In your package.json file, you can specify a scripts property that essentially creates aliases for your commands that npm can run."

Take a note of the following code in package.json.

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"

Modify the scripts section of package.json.

  "scripts": {
    "start": "npx nodemon server.js",
    "test": "echo \"Error: no test specified\" && exit 1"

Now we have a shortcut command to run nodemon.

Try npm start or npm run start again. Here's the result.

> backend@1.0.0 start
> npx nodemon server.js

[nodemon] 2.0.12
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node server.js`
Listening on port 3000

To exit use: Control ⌃C (control + c)

Going further

These sections go into detail about what's happening in the server.js code.


"When Node.js was invented, modules and code encapsulation were high on the priority list. The creators of Node.js were keen for it to not suffer the same fate as the browser by having a big, dangerous global scope. So they implemented Node.js with a module specification called CommonJS (which is where you get the module exports and require syntax from)."

Why your ES6+ syntax doesn't work in Node.js and how to fix it

"As our application grows bigger, we want to split it into multiple files, so called "modules". A module may contain a class or a library of functions for a specific purpose."

"The language-level module system appeared in the standard in 2015, gradually evolved since then, and is now supported by all major browsers and in Node.js."

"CommonJS defines a module format. Unfortunately, it was defined without giving browsers equal footing to other JavaScript environments. Because of that, there are CommonJS spec proposals for Transport formats and an asynchronous require."


"In the Node.js module system, each file is treated as a separate module."

"Require is an import of certain files or packages used with NodeJS's modules. It is used to improve code structure and uses."

Use strict

"Modern JavaScript supports "classes" and "modules" – advanced language structures (we'll surely get to them), that enable use strict automatically. So we don't need to add the "use strict" directive, if we use them."

"So, for now "use strict"; is a welcome guest at the top of your scripts. Later, when your code is all in classes and modules, you may omit it."



// const express = require('express');
import express from 'express';

In server.js, if you change the require statement to an import statement, you should see the following error.

(node:5578) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
import express from 'express';

SyntaxError: Cannot use import statement outside a module
[nodemon] app crashed - waiting for file changes before starting...

When you add the following line to package.json, it works!

"type": "module",

However, require statements won't work any longer.

const express = require('express');

ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and 'Desktop/backend/package.json' contains "type": "module".
To treat it as a CommonJS script, rename it to use the '.cjs' file extension.



Template literals





"The req object represents the HTTP request and has properties for the request query string, parameters, body, HTTP headers, and so on."


"The res object represents the HTTP response that an Express app sends when it gets an HTTP request."




"The Express philosophy is to provide small, robust tooling for HTTP servers, making it a great solution for single page applications, websites, hybrids, or public HTTP APIs."


In this article, we created a server file and added Express boilerplate code. Then, we started the server in a few different ways and resolved the nodemon local install issue. Next, hopefully, you dove into the complex history of modules in Javascript and the additional resources that add insight to the Express server code.