# \[Tutorial\] An Introduction to Node.js Servers (and Express.js)

**URL:** <https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211>\
**Category:** Tutorials\
**Tags:** javascript\
**Created:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211 "2021-04-03T21:20:53Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Josh](https://forum.codeselfstudy.com/user_avatar/forum.codeselfstudy.com/josh/32/4_2.png) [@Josh](https://forum.codeselfstudy.com/u/Josh)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/1 "2021-04-03T21:20:53Z")

</div>

I’m going to try to write some [tutorials](https://forum.codeselfstudy.com/c/tutorials/43) that answer questions that sometimes come up at meetups. I don’t know if this information is too dense or not useful enough, but feedback is welcome and I’ll keep trying to adjust things as I write more. 🙂

## How to Make Node.js Web Servers

This is a short tutorial that explains how Node.js servers work at a basic level. Some of the information applies to web servers in general. If you are a little uncertain about how “the backend” works in general, this tutorial might help.

The tutorials assumes some basic knowledge of JavaScript.

A link to the finished code in a Github repo is at the bottom of this post.

## Install Node.js

To see if Node.js is installed, open a terminal and type this (not including the dollar sign, which just represents the terminal’s prompt).

```plaintext
$ node -v

```

If you have Node installed, you should see output something like `v14.0.0`, which is my current version at the time I updated this tutorial. It’s okay if you see a different version number — the code below should still work.

If you don’t have Node installed yet, you can install it with these instructions: [[Tutorial] How to Install Node.js on Linux, Mac, and Windows](https://forum.codeselfstudy.com/t/tutorial-how-to-install-node-js-on-linux-mac-and-windows/2231)

## Create a Node.js Project

Create a new directory for your server and create a file named `package.json` with the following contents:

```json
{
    "name": "node_server",
    "private": true,
    "version": "0.1.0",
    "description": "A Node.js server example",
    "main": "server.js",
    "scripts": {
        "start": "npx nodemon server.js"
    },
    "license": "BSD-3-Clause",
    "devDependencies": {
        "nodemon": "^2.0.3"
    }
}

```

A `package.json` file provides information about your project and tells Node what other software dependencies are needed in order to run your app.

Then type this to install the dependency:

```plaintext
$ npm install

```

The single dependency there in the `package.json` file is `nodemon`, which is a tool that restarts your Node program whenever you save a file in your project.

The `npm install` should create two new things in the project directory:

- A file named `package-lock.json`. You can ignore that for now and learn about it later. You won’t have to edit it or do much with it in most cases.
- A directory named `node_modules`. That’s where all the dependencies are stored (in this case, just the `nodemon` program). You won’t have to do anything with that directory either, so just leave it for now.

That `package.json` file sets things up so that you can start your server with `npm start` and it will keep reloading your app while you work on it. You could alternatively start the program by typing `node server.js`, but then you would have to manually restart the server every time you change a file.

If you’re using Git (optional), be sure to create a file named `.gitignore` (with the leading dot) and add this line to it:

```plaintext
node_modules/

```

That will prevent you from accidentally saving the dependencies (extra programs that your code depends on, like `nodemon`) in the Git repo.

Now the initial setup is done.

## Writing the Server

Create a file named `server.js` and import Node’s built-in [`http` library](https://nodejs.org/api/http.html) like this:

```javascript
const http = require("http");

```

Importing a library gives your program extra functionality. There are several ways to import functionality into a file in JavaScript (including Node.js) — the most common way to do it in Node.js is called CommonJS, which is the syntax we’re using here.

After writing that first `require` line in the file, you can refer to all the HTTP functionality in that library by using the name `http`.

### A Side Note on CommonJS Imports/Exports

You might hear the word “module” while working with Node.js. A module just means a file. Your module (the file) can only see functions and variables that exist in that file. To get functions from other files your file (module) has to import them. The other file has to explicitly export that functionality as well. A lot of detail about how to do that is beyond the scope of this tutorial, but the short explanation is that you can import functionality from a module (file) like this:

If you have a file named `hello.js` with these contents:

```javascript
// filename: hello.js
function helloWorld() {
    return "hello world";
}

// make the function available for other modules to import
module.exports = helloWorld;

```

you can then import its function in another module (file) like this:

```javascript
// filename: script.js

// import the function that was exported from `hello.js`
const helloWorld = require("./hello");

// now you can use the function from the other module
const result = helloWorld();

console.log(result);
// prints "hello world"

```

If you create those two files and type `node script.js`, it will print the result.

If the other module or library is built-in to Node or was installed with `npm`, you can refer to it just by name like this:

```javascript
const http = require("http");

```

But if the other module is a file in your project, it needs to be referenced by the relative path, using a leading dot. (The dot-slash refers to the current directory that the file sits in). So, to reference the `hello.js` file from the `script.js` file, above, you use a leading dot-slash:

```javascript
const helloWorld = require("./hello");

```

For this tutorial all you really need to know is that the `require` function will import functionality from another library or module and assign it to a name that you can use in the current file.

### Back to the Server Code

The `http` object that you imported has a method named `createServer`. You can use it like this:

```javascript
const server = http.createServer(/* the server's functionality goes here */);

```

To create the server’s functionality, we can pass in a function that has two parameters: `request` and `response`:

```javascript
const http = require("http");

function requestHandler(request, response) {
    console.log("got a request!");
    // To send back a response, you can use the `end` method:
    response.end("here is your response");
}

// Pass the function into the server
const server = http.createServer(requestHandler);

```

There is one more step — run the server. Put the code below at the bottom of the `server.js` file to tell it to listen on port `3333`. Other common ports are `3000`, `8000`, and `8080`. I chose `3333`, because it isn’t commonly used, and you’ll be less likely to see an error than if you use port `3000` which might clash with another app that could be running in another terminal on your computer. 🙂

```javascript
server.listen(3333, () =>
    console.log("server is listening at http://localhost:3333/")
);

```

The complete `server.js` file should now look like this:

```javascript
const http = require("http");

function requestHandler(request, response) {
    console.log("got a request!");
    // To send back a response, you can use the `end` method:
    response.end("here is your response");
}

// pass the function into the server
const server = http.createServer(requestHandler);

server.listen(3333, () =>
    console.log("server is listening at http://localhost:3333/")
);

```

Then try starting the server by typing this in your terminal:

```plaintext
$ npm start

```

The terminal should output something like this:

```plaintext
$ npm start

> npx nodemon server.js

[nodemon] 2.0.3
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node server.js`
server is listening at http://localhost:3333/

```

Don’t worry if the output in your terminal is a little different. The important part is that it should say “`server is listening at http://localhost:3333/`” on the last line.

Open a browser (I recommend [Firefox](http://www.firefox.com/)), and visit `localhost:3333`.

You should see the text you passed to the `response.end` method on the page.

 ![Node.js server example](https://forum.codeselfstudy.com/uploads/default/original/2X/1/1b7f97e85fec76422fe9f33bfc5fa7fc099b3b75.png)

## What Is Happening?

When you type a URL into a browser’s address bar, it sends a request to a server. The request is usually a bit of text that contains information for the server.

It’s possible to inspect that text in the browser. In Firefox, you can open the [Network Monitor](https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor) by pressing Ctrl+Shift+E (or Command+Option+E on Mac). You should see something like the screenshot below.

( **Tip:** for dark mode, check [the settings](https://developer.mozilla.org/en-US/docs/Tools/Settings) or download [Firefox Developer Edition](https://www.mozilla.org/en-US/firefox/developer/).)

 ![Firefox network monitor](https://forum.codeselfstudy.com/uploads/default/original/2X/e/ee25fa553babae16143a1a6e47db2123ec7f00fa.png)

To see the requests, reload the page. Make sure that “All” is selected. You can ignore the line that says “favicon.ico” if it shows up there. The line we’re interested in has a slash (`/`) in the “File” column. A slash represents a directory, and the root directory of your site is just `/`. The URLs for the root of virtually all domains have a slash on the end, though modern browsers misleadingly hide that information in the address bar.1 🤔

 ![Network Monitor requests in Firefox](https://forum.codeselfstudy.com/uploads/default/original/2X/5/50fc0938c07f6469588c9cd6e31000e8dfc84a42.png)

Click on the slash character in the “File” column to open up a pane on the right that will show details about the information your browser is sending to the web server.

 ![Firefox Network Monitor request details](https://forum.codeselfstudy.com/uploads/default/original/2X/c/cd4fbf83a2d0a181dc16fdf4b9915a44a2790332.png)

Click the “Edit and Resend” button on the right and take a look at the raw text that is there. Your version will probably be a little different in places, but on my computer it looks like this:

```plaintext
Host: localhost:3333
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache

```

Those are key-value pairs that allow the browser to tell the server what it should send back.

To see that information on the server side, you can extract the headers out of the request object by using `request.headers`.

Change the `requestHandler` function in the `server.js` file so that it looks like this:

```javascript
function requestHandler(request, response) {
    console.log(request.headers);
    response.end("here is your response");
}

```

Now, when you reload the page in the browser (to resend the request to the server), the server will print something like the following in the terminal:

```javascript
{
  host: 'localhost:3333',
  'user-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0',
  accept: 'image/webp,*/*',
  'accept-language': 'en-US,en;q=0.5',
  'accept-encoding': 'gzip, deflate',
  connection: 'keep-alive',
  pragma: 'no-cache',
  'cache-control': 'no-cache'
}

```

The key-value pairs that were sent by the browser were parsed into a JavaScript object. Since the headers are now a JS object, you can easily use them in your server code.

Those headers aren’t all the information that the browser is sending though. There’s also a bit of information that Firefox displays in the “Request Method” area:

![GET request](https://forum.codeselfstudy.com/uploads/default/original/2X/a/a52233d26f70aa1dbedc5a54fe29bb39bdef4d42.png)

If you want to see what the full raw information looks like you can make a request with a program called `curl`. It’s something like Postman (if you’re familiar with that), but runs in the terminal.

After installing curl (type “how to install curl \<mac, linux, or windows\>” in a search engine), type the following command in a terminal window:

```plaintext
$ curl -v http://localhost:3333/     

```

It will print the outgoing headers, which should look something like this:

```plaintext
GET / HTTP/1.1
Host: localhost:3333
User-Agent: curl/7.47.0
Accept: */*

```

You can also try another path, like a (nonexistent) `/about` page:

```plaintext
$ curl -v http://localhost:3333/about

```

It sends this request:

```plaintext
GET /about HTTP/1.1
Host: localhost:3333
User-Agent: curl/7.47.0
Accept: */*

```

and gets this response:

```plaintext
HTTP/1.1 200 OK
Date: Mon, 13 Apr 2020 02:29:03 GMT
Connection: keep-alive
Content-Length: 21

```

Check your terminal where the server is running, and it should have logged the headers, something like this:

```javascript
{ host: 'localhost:3333', 'user-agent': 'curl/7.47.0', accept: '*/*' }
{ host: 'localhost:3333', 'user-agent': 'curl/7.47.0', accept: '*/*' }

```

The Node server isn’t picking up the first line from the sent information in its own `request.headers` object. To get that information, you can use other functions.

Change the `requestHandler` function so that it looks like this:

```javascript
function requestHandler(request, response) {
    const headers = request.headers;
    // This extracts the method ("GET", "POST", etc.)
    const method = request.method;
    // This extracts the path, like "/" or "/about"
    const url = request.url;

    console.log("headers:", headers);
    console.log("method:", method);
    console.log("url:", url);

    response.end("here is your response");
}

```

Reload `http://localhost:3333/` in the browser and you should see information like this printed in the server’s terminal window:

```plaintext
method: GET

url: /

headers: {
  host: 'localhost:3333',
  'user-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0',
  accept: 'image/webp,*/*',
  'accept-language': 'en-US,en;q=0.5',
  'accept-encoding': 'gzip, deflate',
  connection: 'keep-alive',
  pragma: 'no-cache',
  'cache-control': 'no-cache'
}

```

If you instead load `http://localhost:3333/about`, the `url` will change to `/about`.

If you make a POST request to the server with `curl`, the `method` will change from `GET` to `POST`. Try it by sending a `POST` request with this command:

```plaintext
$ curl -X POST http://localhost:3333/

```

The output in the server’s terminal will show that it knows that it has received a `POST` request:

 ![curl POST request](https://forum.codeselfstudy.com/uploads/default/original/2X/8/8c8209254742cd846a648f281526cd792f13ce93.png)

## Where Things Are Going

Now that our server can see what information the browser is requesting, it can conditionally send back responses based on the information it receives.

Change the `requestHandler` function so that it looks like this:

```javascript
function requestHandler(request, response) {
    const url = request.url;

    // This is a primitive server-side router.
    if (url === "/") {
        response.end("home page");
    } else if (url === "/about") {
        response.end("about page");
    } else {
        response.end("page not found");
    }
}

```

Then load these three URLs in your browser to see the responses:

- `http://localhost:3333/`
- `http://localhost:3333/about`
- `http://localhost:3333/doesnt-exist`

The response that the server sends back will now change based on what URL your browser requested. 🚀

## Why People Use Web Frameworks

You could slowly build up the functionality of your server by adding functions to do more-robust routing, read in template files, send back proper status codes, store cookies, and all the other tasks a website usually needs, but most people don’t want to write a whole web framework from scratch each time they build a website.

That’s what server-side web frameworks are for.

You can build a web server in any language, and there are web frameworks in just about every common language. The most common one for Node.js is called Express.js.

Express.js handles a lot of the common boilerplate for you so don’t have to write it yourself. Express is lightweight and doesn’t have a lot of features, but there are many libraries that you can use to quickly add functionality.

## A Simple Express Server

It’s easy to change our existing server so that it uses Express.js.

Stop the Node server we wrote by pressing Ctrl+c in the terminal window where it’s running.

Then install Express in the project by typing:

```plaintext
$ npm install --save express

```

Change the `server.js` file so that it contains this code:

```javascript
// import express
const express = require("express");

// create an Express application
const app = express();

// define what the pages should send
function homePage(request, response) {
    response.send("home page");
}

function aboutPage(request, response) {
    response.send("about page");
}

// Mount the pages at the desired paths.
//
// Note that Express checks for the `GET` method by
// using `app.get`. If you wanted to listen for `POST`
// requests, then you would use `app.post`.
app.get("/", homePage);
app.get("/about", aboutPage);

app.listen(3333, () =>
    console.log("server is running at http://localhost:3333/")
);

```

Then start the server again with `npm start` and try visiting these three URLs:

- `http://localhost:3333/`
- `http://localhost:3333/about`
- `http://localhost:3333/doesnt-exist`

The server should behave in a similar way as our lower-level Node.js server, but now there are a lot of built-in features that can make developing a real website much easier.

## Adding More Features

In order to have our app serve HTML, we can add a templating engine. There are many options to choose from — I like Handlebars.js. To install it, stop the server with Ctrl+c and type:

```plaintext
$ npm install --save hbs

```

Then add these three lines to the `server.js` file:

```javascript
const path = require("path");
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "hbs");

```

That tells Express to use Handlebars and to look inside a directory named `views` for the HTML templates.

Create the `views` directory and put a file in it name `page.hbs`. The basic structure of your app should look something like this (possibly with some extra stuff in it, but these are the important files):

```plaintext
.
├── package.json
├── package-lock.json
├── server.js
└── views
    └── page.hbs

```

The `page.hbs` file should contain this content:

```auto
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>{{title}}</title>
    </head>
    <body>
        <nav>
            <a href="/">Home</a> | <a href="/about">About</a>
        </nav>
        <h1>{{title}}</h1>
        <p>{{body}}</p>
    </body>
</html>

```

Then update your `server.js` file so that it looks like the code below. The parts that changed are the two functions, `homePage` and `aboutPage`.

```javascript
const express = require("express");
const path = require("path");

const app = express();

app.set("views", path.join(__dirname, "views"));
app.set("view engine", "hbs");

function homePage(request, response) {
    // This data object could come from a database or anywhere you want.
    const pageData = {
        title: "Home Page",
        body: "content coming soon",
    };
    response.render("page.hbs", pageData);
}

function aboutPage(request, response) {
    const pageData = {
        title: "About Page",
        body: "lorem ipsum",
    };
    response.render("page.hbs", pageData);
}

// mount the pages at the desired paths
app.get("/", homePage);
app.get("/about", aboutPage);

app.listen(3333, () =>
    console.log("server is running at http://localhost:3333/")
);

```

The `response.render` method takes two arguments: the name of a Handlebars file in the `views` directory, and a JavaScript object that contains the data that should be injected into the Handlebars template.

Since the `page.hbs` Handlebars template contains placeholders for two variables, named `title` and `body`, like this…

```plaintext
<h1>{{title}}</h1>
<p>{{body}}</p>

```

…we can pass the template a JavaScript object that has keys that match those variable names:

```javascript
// a JS object with keys that match the template variables
const pageData = {
    title: "Home Page",
    body: "content coming soon",
};

// pass the JS object to the template
response.render("page.hbs", pageData);

```

Express’ `response.render` method will then send the server-rendered HTML to the browser.

Both pages should now display correctly, even though they are simple.

Here is the output from `http://localhost:3333/`

 ![Home Page](https://forum.codeselfstudy.com/uploads/default/original/2X/f/f60e5482ae69995ca9c2402478e80ad80e3daa6f.png)

And here is the output from `http://localhost:3333/about`

 ![About Page](https://forum.codeselfstudy.com/uploads/default/original/2X/0/0e27a7e338da2e904ab95cdaefba279938f1cd37.png)

One HTML (or Handlebars) template is able to render different content, and the data is cleanly separated from the display of that data (“the view”).

You can navigate between the pages with the menu at the top of the page.

## Add Static Assets

The next step is to add a little styling. The `server.js` file needs one line of code to tell Express where to find the static assets, like frontend JS and CSS.

Right after these two lines in `server.js`…

```javascript
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "hbs");

```

…add this line:

```javascript
app.use(express.static(path.join(__dirname, "public")));

```

That tells express to look in a directory named `public` for the static files. Create the `public` directory and add two files to it, named `main.js` and `styles.css`. The structure if the project should look something roughly like this now:

```plaintext
$ tree -I node_modules
.
├── package.json
├── package-lock.json
├── public
│ ├── main.js
│ └── styles.css
├── server.js
└── views
    └── page.hbs

```

Update the `page.hbs` file so that it now looks like this with the stylesheet and JavaScript files included:

```plaintext
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>{{title}}</title>
        <link rel="stylesheet" href="/styles.css">
    </head>
    <body>
        <nav>
            <a href="/">Home</a> | <a href="/about">About</a>
        </nav>
        <h1>{{title}}</h1>
        <p>{{body}}</p>
        <script src="/main.js"></script>
    </body>
</html>

```

There are two new lines there that load the following assets:

- `main.js`
- `styles.css`

To make sure that everything is wired together correctly, put the following code into the files in your `public` directory.

For `public/main.js`:

```javascript
console.log("hello world");

```

For `public/styles.css`:

```css
body {
    color: teal;
}

```

Save the files and reload `http://localhost:3333/` to make sure that the frontend CSS and Javascript files are loading. The text color should change, and the browser console should have logged “hello world”.

 ![image](https://forum.codeselfstudy.com/uploads/default/original/2X/5/50ced2d31e6842cd1b219c38d67cbe84d2be1528.png)

## Where to Go From Here

If you want, you can try making additional pages, editing the CSS, and or JS, and tinkering with the site.

The [Express.js docs](https://expressjs.com/) are good.

### Extra: Middleware

The way that [middleware](https://expressjs.com/en/guide/writing-middleware.html) works in Express is interesting. A middleware is just a function that accepts three arguments: a `request`, `response`, and optionally a `next`. You can manipulate the `request` and `response` and then call `next` to send the request on to the next middleware in the chain.

Here’s an example of a custom logging middleware that you could put near the top of your `server.js` file that would log the method and path of every request:

```javascript
// This works as middleware because it takes three args and
// calls the third one at the end.
function loggingMiddleware(request, response, next) {
    // logs some data
    console.log(`received a ${request.method} request to ${request.url}`);

    // sends on the request to the next middleware function
    next();
}

// Mount the middleware on the app
app.use(loggingMiddleware);

```

The server will then print out the logging information like this:

 ![Express loggin middleware](https://forum.codeselfstudy.com/uploads/default/original/2X/0/0c69772ef02c5c35569576c8f6704b71b685524d.png)

Express is built with chains of middleware functions — even the routing functions are middleware. They take `request` and `response`, but because they are the last middleware in the chain, instead of calling `next()` they call a method like `response.render` to send the result back to the browser.

The example logging middleware runs on all routes, because it wasn’t passed a route parameter:

```javascript
// This middleware runs on all routes.
app.use(loggingMiddleware);

```

If `app.use` is given a route, then the given middleware function will only run on that route. That’s how the router sends the results of specific middleware functions when it receives requests to certain routes, like the About Page:

```javascript
// This middleware only runs on http://localhost:3333/about
app.use("/about", aboutPage);

```

It might take a while of tinkering with Express before the middleware concept makes sense, but go through a few Node.js tutorials and poke around in the docs a bit, and it will start to become clearer.

If anyone has questions or notices any errors, leave a comment below. 🙂

The final code can be downloaded from [the Github repo](https://github.com/j127/express_server_tutorial).

If you want to add a database, try this: [[Tutorial] How to Use MySQL or MariaDB with Node.js and Express](https://forum.codeselfstudy.com/t/tutorial-how-to-use-mysql-or-mariadb-with-node-js-and-express/2260/1)

* * *

#### Footnotes

1 To fix URL trimming in Firefox, type `about:config` in the address bar to open up the Advanced Preferences page. Ignore the warning about a warranty if you see it. Filter the items for the word “trim” and look for the setting named `browser.urlbar.trimURLs`. Double-click it to set it to `false`, and then close the tab. The browser should display full URLs correctly after that. Here’s a screenshot:

 ![Firefox don't trim URLs](https://forum.codeselfstudy.com/uploads/default/original/2X/2/23538da28f30a776e6a79a37e388d114d6f8a7d2.png)

---

<div class="post-metadata">

**Author:** ![flcpge](https://forum.codeselfstudy.com/user_avatar/forum.codeselfstudy.com/flcpge/32/653_2.png) [@flcpge](https://forum.codeselfstudy.com/u/flcpge)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/2 "2021-04-03T21:20:53Z")

</div>

Nice write up Josh. 🙂

---

<div class="post-metadata">

**Author:** ![OutsourcedGuru](https://forum.codeselfstudy.com/user_avatar/forum.codeselfstudy.com/outsourcedguru/32/983_2.png) [@OutsourcedGuru](https://forum.codeselfstudy.com/u/OutsourcedGuru)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/3 "2021-04-03T21:20:53Z")

</div>

```auto
npm install -g express-generator
cd ~/sites # ...or wherever you collect your website projects
express --ejs test # Scaffold an Express app called test
cd test
npm install
DEBUG test:* npm start # Bring it up with debug logging
# Ctl-C
code . # Assuming that you have Visual Studio Code to start editing

```

---

<div class="post-metadata">

**Author:** ![Josh](https://forum.codeselfstudy.com/user_avatar/forum.codeselfstudy.com/josh/32/4_2.png) [@Josh](https://forum.codeselfstudy.com/u/Josh)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/4 "2021-04-03T21:20:53Z")

</div>

I didn’t include that because it was already getting long. 🙂

I usually pass in Handlebars like this…

```nohighlight
$ express --view=hbs appname

```

…and then restructure everything except for parts of the `app.js` and `bin/www` files something like this:

```nohighlight
.
├── bin
├── controllers
├── db
├── helpers
├── models
├── public
│ ├── fonts
│ ├── images
│ ├── js
│ └── styles
├── routes
└── views

```

I’ve been meaning to write a custom Express generator, but haven’t done it yet.

---

<div class="post-metadata">

**Author:** ![OutsourcedGuru](https://forum.codeselfstudy.com/user_avatar/forum.codeselfstudy.com/outsourcedguru/32/983_2.png) [@OutsourcedGuru](https://forum.codeselfstudy.com/u/OutsourcedGuru)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/5 "2021-04-03T21:20:53Z")

</div>

I know that I’ll be using this tomorrow to scaffold yet another project. It’s such a time saver.

---

<div class="post-metadata">

**Author:** ![PaulH](https://forum.codeselfstudy.com/letter_avatar_proxy/v4/letter/p/e495f1/32.png) [@PaulH](https://forum.codeselfstudy.com/u/PaulH)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/6 "2021-04-03T21:20:53Z")

</div>

OK, I just went through this, and coming from PHP this is making sense now. I also see the power of handlebars!

Basically to me, the advantage of node over PHP is all the dynamic async things you can do. AJAX helps with that of course, but is more cumbersome. Hmmm

I am going to push through with this.

As for feedback on the tutorial I had to run all the installs using `sudo` . So it might be good to put a note in about that.  
I.E. `sudo npm install `

Also is `require` in node like `include` in PHP? It seems that way to me.

Thanks again for this, I am going to try port a few pages of my site! 🙂

Oh, and another fun thing (for me) I was able to edit and all the files and folders in terminal. I did use nano though. 😉

---

<div class="post-metadata">

**Author:** ![Josh](https://forum.codeselfstudy.com/user_avatar/forum.codeselfstudy.com/josh/32/4_2.png) [@Josh](https://forum.codeselfstudy.com/u/Josh)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/7 "2021-04-03T21:20:53Z")

</div>

## AJAX

AJAX works with node in a similar way as PHP. In PHP the steps would look almost the same, but just with different syntax. I’ll write an example below.

If you start the node server and visit `localhost:3333/api` (after making sure the API route from the [example repo](https://github.com/j127/express_server_tutorial) has been added) it should return some JSON. You can fetch that JSON with AJAX by opening the browser console while on a `localhost:3333` page and typing:

```javascript
fetch("/api")
    .then(res => res.json())
    .then(json => console.log("here is the JSON response", json));

```

and it should print out the JSON response from the server.

## sudo

If the terminal asks for `sudo` when installing npm packages, Node probably isn’t set up correctly. I’m guessing that Node wasn’t installed with `nvm`. If you want to fix it (possible security risk), send me a chat message and I could walk through the steps on how to uninstall and [reinstall node using `nvm`](https://forum.codeselfstudy.com/t/tutorial-how-to-install-node-js-on-linux-mac-and-windows/2231).

## require

I think in PHP it would be more like [`use`](https://www.tutorialspoint.com/php7/php7_use_statement.htm), but I haven’t used much PHP in years and don’t remember the syntax. I think `include` injects the entire other PHP file into the current file, while `use` or `require` just imports specific functions that are allowed to be exported from the other file.

## PHP server

You can compare the Express code with modern PHP code by looking at a similar framework for PHP called [Slim](http://www.slimframework.com/).

I added some comments to their sample code from the homepage:

```php
<?php
// This is like `require` in Node. Each line imports some functionality
// from another PHP library. In Node, the file that lists the
// dependencies is called `package.json`. In PHP, it's called
// `composer.json`. Here, it's importing `Request` and `Response` as
// well as `AppFactory`, which is like the Node.js line that requires
// `express`.
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

// This is PHP code to load the dependencies.
require __DIR__. '/../vendor/autoload.php';

// This is like `const app = express()` in Node/Express
$app = AppFactory::create();

// This is like the `app.get("/hello", function(request, response) ...` lines in Express.
$app->get('/hello/{name}', function (Request $request, Response $response, array $args) {
    $name = $args['name'];
    $response->getBody()->write("Hello, $name");
    return $response;
});

// This is like `app.listen(...)` in Express code
$app->run();

```

Nearly all major languages let you create servers with similar steps: Python/Flask, Ruby/Sinatra, etc.

---

<div class="post-metadata">

**Author:** ![PaulH](https://forum.codeselfstudy.com/letter_avatar_proxy/v4/letter/p/e495f1/32.png) [@PaulH](https://forum.codeselfstudy.com/u/PaulH)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/8 "2021-04-03T21:20:53Z")

</div>

OK, got it, thanks! I am working my way through handlebars, but will try the API and re-installing node after that, and check back in. 🙂

---

<div class="post-metadata">

**Author:** ![Josh](https://forum.codeselfstudy.com/user_avatar/forum.codeselfstudy.com/josh/32/4_2.png) [@Josh](https://forum.codeselfstudy.com/u/Josh)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/9 "2021-04-03T21:20:53Z")

</div>

I just wrote the rest of the post. I think I accidentally hit `ctrl-enter`, which submits the post. 🤔

Handlebars is for returning HTML content. If you want to return JSON, have the function return `res.json` instead of `res.render`.

```javascript
// To send HTML from a template
function aboutPage(request, response) {
    const someData = { /* get data from the DB here */ }; 
    res.render("templateName.hbs", someData);
}

// To send JSON from a JS object
function apiPage(request, response) {
    const someJavaScriptObject = { /* get data from the database here */ }; 
    res.json(someJavaScriptObject);
}

```

---

<div class="post-metadata">

**Author:** ![PaulH](https://forum.codeselfstudy.com/letter_avatar_proxy/v4/letter/p/e495f1/32.png) [@PaulH](https://forum.codeselfstudy.com/u/PaulH)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/10 "2021-04-03T21:20:53Z")

</div>

Nice! Can I inline CSS in handlebars? Just searching how to do that.  
Usually with PHP I have separate CSS files and then use `include` to inline them for faster loading.

Edit: I guess I can just include plain CSS with partials? 🤷‍♂️

---

<div class="post-metadata">

**Author:** ![PaulH](https://forum.codeselfstudy.com/letter_avatar_proxy/v4/letter/p/e495f1/32.png) [@PaulH](https://forum.codeselfstudy.com/u/PaulH)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/11 "2021-04-03T21:20:53Z")

</div>

Question on handlebars.  
I want to build my pages using partials like header, css, and footer.  
I read the docs, but I am not sure where I register the partial

[https://handlebarsjs.com/guide/partials.html#basic-partials](https://handlebarsjs.com/guide/partials.html#basic-partials)

`Handlebars.registerPartial("myPartial", "{{name}}");`

Also, is there a way to reference the partial in the folder?

---

<div class="post-metadata">

**Author:** ![Josh](https://forum.codeselfstudy.com/user_avatar/forum.codeselfstudy.com/josh/32/4_2.png) [@Josh](https://forum.codeselfstudy.com/u/Josh)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/12 "2021-04-03T21:20:53Z")

</div>

> [@PaulH](#):
>
> I guess I can just include plain CSS with partials?

I haven’t tried it, but I think that would work.

> [@PaulH](#):
>
> I am not sure where I register the partial

Are you using Express.js or just Handlebars by itself?

---

<div class="post-metadata">

**Author:** ![PaulH](https://forum.codeselfstudy.com/letter_avatar_proxy/v4/letter/p/e495f1/32.png) [@PaulH](https://forum.codeselfstudy.com/u/PaulH)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/13 "2021-04-03T21:20:53Z")

</div>

As far as I know I am using express per the tutorial above.

I actually have not made any changes to the server.js code yet. So just porting to the home page…

---

<div class="post-metadata">

**Author:** ![Josh](https://forum.codeselfstudy.com/user_avatar/forum.codeselfstudy.com/josh/32/4_2.png) [@Josh](https://forum.codeselfstudy.com/u/Josh)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/14 "2021-04-03T21:20:53Z")

</div>

I think you can put this in the `server.js` file:

```javascript
// this goes at the top
const hbs = require('hbs');

```

Look for the line that sets the view engine and code after it:

```javascript
// look for this line
app.set("view engine", "hbs");

// add this below that one
hbs.registerPartials(__dirname + '/views/partials');

```

Then create a directory at `views/partials/` and put your partials there.

An example partial file at `views/partials/footer.hbs` might look like this:

```auto
<footer class="container" id="mainFooter">
    <hr />
    Copyright &copy; 2020 {{siteName}}
</footer>

```

Then your `layout.hbs` file could include any partial files like this:

```auto
{{> navbar}}
{{{body}}}
{{> footer}}

```

I haven’t tested that recently but am copying from some old code I wrote in 2017. If it doesn’t work, let me know.

---

<div class="post-metadata">

**Author:** ![PaulH](https://forum.codeselfstudy.com/letter_avatar_proxy/v4/letter/p/e495f1/32.png) [@PaulH](https://forum.codeselfstudy.com/u/PaulH)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/15 "2021-04-03T21:20:53Z")

</div>

Thanks for that! It was close to working, looks like in addition to the line where you define the path to the partials you also need a line to define each partial like so:  
`hbs.registerPartial("myPartial", "{{footer}}");`

It is working now, I will report back if I can inline css! 🙂

---

<div class="post-metadata">

**Author:** ![PaulH](https://forum.codeselfstudy.com/letter_avatar_proxy/v4/letter/p/e495f1/32.png) [@PaulH](https://forum.codeselfstudy.com/u/PaulH)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/16 "2021-04-03T21:20:53Z")

</div>

So question: Does the server.js have to contain every route for every page?  
I do have template pages in my tools subdomain, but I also have a lot of static pages that are “articles”. Do I have to route to all those articles?

Also, if I have to route to every server-generated page, I feel like the server.js is going to be a very large file. Is that right?

---

<div class="post-metadata">

**Author:** ![Josh](https://forum.codeselfstudy.com/user_avatar/forum.codeselfstudy.com/josh/32/4_2.png) [@Josh](https://forum.codeselfstudy.com/u/Josh)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/17 "2021-04-03T21:20:53Z")

</div>

Is there one separate file for each page on the server, or does the page content come from a database?

> [@PaulH](#):
>
> Also, if I have to route to every server-generated page, I feel like the server.js is going to be a very large file. Is that right?

I’ll post an example of how you can split things up into multiple files below.

---

<div class="post-metadata">

**Author:** ![flcpge](https://forum.codeselfstudy.com/user_avatar/forum.codeselfstudy.com/flcpge/32/653_2.png) [@flcpge](https://forum.codeselfstudy.com/u/flcpge)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/18 "2021-04-03T21:20:53Z")

</div>

I separate my routes. For example I separate my stressors routes from the rest of server.js.

```auto
const express = require("express");
const morgan = require("morgan");
const mongoose = require("mongoose");

const { PORT, DATABASE_URL } = require("./config");
const { Stressor } = require("./models");
const stressorsRouter = require("./stressorsRouter");

const app = express();

app.use(morgan("common"));
app.use(express.static("public"));

/* Route requests that come to the `/stressors` endpoint
to the Express router instance in the stressorsRouter module. */
app.use("/stressors", stressorsRouter);

mongoose.Promise = global.Promise;

```

---

<div class="post-metadata">

**Author:** ![Josh](https://forum.codeselfstudy.com/user_avatar/forum.codeselfstudy.com/josh/32/4_2.png) [@Josh](https://forum.codeselfstudy.com/u/Josh)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/19 "2021-04-03T21:20:53Z")

</div>

I made a longer example of one way to do it and posted it on Github: [https://github.com/j127/express\_structure](https://github.com/j127/express_structure)

The `app.js` (same idea as `server.js` above) file imports the routes on [these lines](https://github.com/j127/express_structure/blob/master/app.js#L8) (the way that flcpge mentioned).

Then the routers get mounted [here](https://github.com/j127/express_structure/blob/master/app.js#L24) at three different paths:

- `/`
- `/things`
- `/api`

Then the router mounts controller functions on the routes. Example, the [thing router](https://github.com/j127/express_structure/blob/master/routes/things.js) sends requests for `localhost:3000/things` to [this function](https://github.com/j127/express_structure/blob/master/controllers/thingController.js#L5) in the `thingsController.js` file.

Another example:

- The app mounts the page router [here](https://github.com/j127/express_structure/blob/master/app.js#L25).
- The [page router says](https://github.com/j127/express_structure/blob/master/routes/index.js#L8) that when the user requests `/about` to run [this function](https://github.com/j127/express_structure/blob/master/controllers/pageController.js#L12) in the page controller

I used the words “page”, “thing”, and “api” in the example code — you could do similar things with any content type (“page”, “article”, “food”, etc.).

---

<div class="post-metadata">

**Author:** ![PaulH](https://forum.codeselfstudy.com/letter_avatar_proxy/v4/letter/p/e495f1/32.png) [@PaulH](https://forum.codeselfstudy.com/u/PaulH)\
**Post date:** [April 3, 2021, 9:20pm UTC](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211/20 "2021-04-03T21:20:53Z")

</div>

At this point, I have another question actually. If I render the handlebars page using Node will the `{{variables}}` still be there for subsequent client sideloading? Or put another way, will the template still be there for client side loading?

How does it then work for subsequent loads on the client side?  
Do I have to render a handlebars template that then gets populated on the client side? With a handlebars library on the client side?  
Or do I still use `document.getElementById`?

[Next page](https://forum.codeselfstudy.com/t/tutorial-an-introduction-to-node-js-servers-and-express-js/2211.md?page=2)
