Learning Node.js — Part 3

Deeper Dive into Express — Middleware, Environments, Configuration, Environment Variables, Debugging, Templating Engines, Database Integration, Properly Restructuring Our Express Routes/Files

Osha Groetz
5 min readApr 18, 2021
These Blog Posts are a Series of My Notes While Following Along: ‘Programming With Mosh’

Express Middleware

Express is a bunch of middleware functions. Middleware functions are called sequentially. Every route handler function ( (req, res) => {res.send(‘Hello World’)} ) is technically a middleware function.

Built-In Middleware²

express.json() — middleware: parses body of the request, if there’s a json object it populates req.body property

express.urlencoded() — middleware: parses incoming requests with url encoded payloads parses req.body like a json object

express.static(‘public’) — all of the static assests of the app will live in a ‘public folder’ (((create that folder in the main folder)))

Code Snippet of Built In Middleware

Custom Middleware

Custom middleware functions should be built in separate files/modules.

Example:

logger.js file:

index.js file:

Third-party Middleware

Express middleware modules can be found here. We are going to use one called Helmet³. Helmet secures Express apps by setting various HTTP headers. To install, type in terminal: npm i helmet .

Another third-party middleware we will use is Morgan⁴. Morgan is used for logging HTTP requests. To install, type in terminal: npm i morgan . (((Note: Morgan should really only be used in production, for the majority of the time)))

Morgan logging the HTTP request with ‘tiny’ format, want more details? Use another format

Environments

Code runs in different Environments: ie: development or production. Disabling or enabling certain features is important in different environments. refresher: process ==> global object in Node that gives us access to the current process
process.env.NODE_ENV ==> returns the environment for this node application (if not set returns undefined)
Can set the NODE_ENV to: development, testing, staging or production.

The code below shows how to only ‘use’ Morgan when in development mode:

To Set App to Production Mode:

Make sure to shut down your server (control-C), then type terminal command: export NODE_ENV=production . You’ll see that although ‘Morgan enabled…’ had been logged in while the app was in development mode, the message does not show up in production mode and Morgan is successfully disabled while in production.

Storing App Configuration Settings & Overwriting in Each Environment

For this example, in dev environment, going to use different database.

Most popular Node package for managing configuration: rc⁵ ; ‘configuration loader for lazy people’ . To install npm, in terminal type: npm i rc .

Will use a different package for this example: config. ‘Node-config organizes hierarchical configurations for your app deployments.⁶’ To install npm, in terminal type: npm i config .

In your application, create a new folder in the main folder: config .(1) Add a default configuration file in this folder: default.json . (2) Add a development config file: development.json . (3) Add a production config file: production.json .

In any of these files, you can over-write a previously declared setting or add additional settings.

default.json file
development.json file
production.json file

Back in index.js file:

index.js file

(((to change back to development environment, type terminal command: export NODE_ENV=development )))

Different configs for different environments

*Don’t store any config secrets in these config files! Store them in environment variables.

Environment Variables

Setting env vars: Type in terminal: export <app_name>_password=1234 .

In development, we add these passwords in manually, but in production environment, these will need to get stored in config panel of host.

Now we need to read the env variables in our app. Add another file in config folder: custom-environment-variables.json . In this file we map config settings to environment variables. (In the code below, you’ll see my app’s name is ‘nodejsbasics’)

custom-environment-variables.json file

Back in index.js file, let’s display password (Line 17), but remember: you don’t ever want to do this in real applications, just for this example.

index.js file

Debugging

Using debug function instead of console.log:

To install the debug package, type in terminal: npm i debug . Add lines 1 & 2 to your code in index.js and change the console.log on line 10 to the startupDebugger.

index.js file

Back in your terminal stop your server and type in command: export DEBUG=app:startup . Restart your server. You will see the message ‘Morgan enabled…’ in the app:startup namespace.

To reset your app so you don’t see debug info, type in terminal: export DEBUG= . You will no longer see any messages.

To see debugging messages from multiple namespaces: export DEBUG=app:startup,app:db (no space after comma). To see all the bugging messages from app namespace, type in terminal: export DEBUG=app:* .

To set env variable for debugger at runtime, stop your server, type in terminal: DEBUG=app:db nodemon index.js .

Templating Engines

When you need to return HTML markup to client instead of JSON objects. *This is NOT necessary for the app we are building as a backend server.

Pug, Mustache, EJS, etc, are common templating engines. To install Pug, type terminal command: npm i pug .

In your index.js file, set up lines 9 & 10. Line 10 is optional. We also change line 36 from res.send to a res.render:

In your main application folder, set up a new folder: views. Inside views, start a new file: index.pug .

If you now restart app and visit http://localhost:3000/, you should the bolded header ‘Hello’. If you ‘View Page Source’ you’ll see:

View Page Source — To see HTML Markup

Integrating the Database

There are many different database options to use, see the list here. We’ll use the MongoDB driver. To install MongoDB, type terminal command: npm install mongodb . Mongoose is built on top of the MongoDB driver. Mongoose is a simpler API and that is what we will use.

Authentication

Express doesn’t have an opinion — later in the course we learn how to secure API Endpoints

How To Structure Application

Let’s refactor our code in index.js and put all of our routes, etc in their own files.

In root of project, new folder: routes . New file in routes: musicians.js .

routes/musicians.js

index.js will now look like this:

index.js

Now, we’ll have our ‘/’ or home route in it’s own file in the route folder as well:

Now our index.js file only has startup code.

Side Note: The logger.js file was moved into a new folder named ‘middleware’

--

--

Osha Groetz

Software Engineer. React, Javascript, Typescript, HTML, CSS, Ruby, Ruby On Rails