Module 4 - Deployment & Best Practices

Extract Configuration into Environment Variables

When you develop and run code on your machine, you run code in its development environment.

Most companies will have a testing environment similar to production; it has the same versions of software and runs on similar, albeit weaker, hardware. They do this to mitigate the risks when moving the to production servers that clients use.

Ideally, all environments run on the same stack, platforms, and versions. Still, it is common to have developers on the Windows platform with the latest version of Node.js and the production server running on Linux with the last stable version of Node.js. For those cases, it is essential to have a testing/staging environment that also runs the Linux and Node.js versions found on the production server. A staging environment can detect any regressions that may occur during deployment before code reaches the user.

How to Build It

Let's code along as we prepare our API for deployment by making the port number configurable through environment variables.

Starter Code

You can find the starter code for this tutorial in this repository.

Add "start" script

When we deploy the API, Heroku and similar services will look for a "start" script that uses node to run the server. We need to add that script to package.json.

Add a "start" script that uses node instead of nodemon to run index.js.

The "scripts" section of package.json should look like so:

"scripts": {
   "start": "node index.js",
   "server": "nodemon index.js"
},

After this change, the hosting service knows how to start our server but needs to control which port the API will use. The port is hard-coded as 9000, and we need to make it dynamic.

Make the Port Dynamic

  1. Read up on the dotenv npm module.
  2. Install dotenv as a production dependency.
  3. Change index.js:
// it's recommended to load configuration for .env as early as possible
require('dotenv').config(); // add this line as the first thing to run

// server code...

// we'll read the port from the server environment if it is there
// Heroku for example will have the PORT environment variable set already
const port = process.env.PORT || 9000;

// we can now use that port, use 9000 as a default if not set by either Heroku or an .env file
server.listen(port, () => {
  console.log(`\n*** Server Running on http://localhost:${port} ***\n`);
});

Add a .env file to the root folder (next to package.json) with the following content:

PORT=9001

It is recommended to add .env to .gitignore to prevent it from being uploaded to GitHub.

The reason is that most systems add configuration secrets to that file that are different between environments. Some examples are database connection credentials or API keys for external services.

  • Stop the server and restart it again, or the server will not detect the change to .env.
  • The API should be using port 9001 now as specified in .env.

Deploy to a Hosting Service

In this lesson, we'll deploy an Express API to Heroku. Heroku is the most pragmatic service for deploying a full-stack personal project for potential employers to see. However, as of November 2022 Heroku does not provide a totally free tier like they used to, so we do not expect you to use their services. We only need you to understand how to make an API deployable to Heroku or similar providers.

How to Build It

This tutorial works with this repository. It contains an Express server that is deployable thanks to two key features:

  • It contains a "start" script that launches server with Node (not Nodemon).
  • The port number is pulled from the environment, instead of it being hard-coded in the file.

Setup Continuous Deployment from GitHub

  1. Login to Heroku and create an app.
  2. In the "Deploy" tab, select GitHub in the "Deployment Method" section.
  3. Heroku will ask GitHub for authorization to access. You need to approve access.
  4. Search for the repository you wish to deploy and click Connect. You can use a fork of the repo linked above.
  5. In the "Automatic deploys" section, pick the "main" branch and click "Enable Automatic Deploys".
  6. In the "Manual deploy" section, click on "Deploy Branch" to kick-start the first deployment.
  7. Scroll to the top and move to the "Overview" tab to see the deployment in action.
  8. On the top right, click "Open App".

The deployment succeeded! If upon opening you app you encounter an error, make sure to have a "start" script in the package.json and to pull the port number from process.env.

Use Postman to connect to the API and get some data.

Add an Environment Variable on Heroku

  1. Change the GET endpoint to greet a friend whose name is pulled from the environment of the machine.
server.get('/hello', (req, res) => {
  res.json(`hello, ${process.env.FRIEND || "my friend"}!`);
});
  1. Add the FRIEND to a .env file at the root of your project.
FRIEND="Jess"
  1. Restart the server running on localhost.
  2. Request the /hello endpoint on localhost to verify that the FRIEND property is set locally, either from the .env file or from the "my friend" fallback.
  3. Commit and push to GitHub.
  4. Once the new changes are deployed, refresh the application on Heroku. Note that we get the default "hello, my friend" message because the environment variable does not exist on Heroku.

Now we are going to add that configuration variable on Heroku.

  1. On Heroku, go to the "Settings" tab.
  2. Click on "Reveal Config Vars" in the "Config Vars" section.
  3. Add a FRIEND config var with the value "Luke"
  4. Refresh the application.

Note that the environment variable on Heroku overrides the default value set in the code, and overrides the value set in the local .env file (which is git-ignored and thus never pushed to GitHub nor deployed). We can use environment variables to store API keys, database connection information, and other secrets more securely.

Module 4 Project: Deployment and Best Practices

The module project contains advanced problems that will challenge and stretch your understanding of the module's content. The project has built-in tests for you to check your work, and the solution video is available in case you need help or want to see how we solved each challenge, but remember, there is always more than one way to solve a problem. Before reviewing the solution video, be sure to attempt the project and try solving the challenges yourself.

Instructions

The link below takes you to Bloom's code repository of the assignment. You'll need to fork the repo to your own GitHub account, and clone it down to your computer:

Starter Repo: Node API 4

  • Fork the repository,
  • clone it to your machine, and
  • open the README.md file in VSCode, where you will find instructions on completing this Project.
  • submit your completed project to the BloomTech Portal

Solution

Additional Resources