Use Environment Variables With Node.js and MongoDB

Defining and using environment-specific configuration variables within code files is less than ideal due to security reasons as well as the coupling of environment-specific configuration and application code. In this lesson, we'll avoid declaring our MongoDB environment variables directly in our database connection file and instead use the popular dotenv package to load environment variables from a .env file.

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL course and can be unlocked immediately with a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL with a single-time purchase.

Thumbnail for the \newline course TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL
  • [00:00 - 00:13] In the last lesson, we hard coded our MongoDB environment variables directly into our code. We created a user variable, a user password variable, and a cluster variable in our database index file.

    [00:14 - 00:25] And we've obtained these values directly from our MongoDB Atlas dashboard. Now having these values so available here is a bad idea for some reasons.

    [00:26 - 00:39] First and foremost, these environment variables should be confidential. We should be wary of having them so publicly available, especially if we start to consider pushing our code to an online repository.

    [00:40 - 00:50] Second, as the name suggests, environment variables are for setting up our apps runtime environment. They don't really have anything to do with our apps logic.

    [00:51 - 01:06] What if, for example, we wanted to change our MongoDB user password as our application has already been built? What we'd want to do is just update an environment variable somewhere rather than having to go into the source code and changing it.

    [01:07 - 01:25] And this is especially helpful in limiting the need to modify and redeploy our app due to changes in configuration, especially if the app is already deployed. In Node, Process is a global object with information about the currently running process.

    [01:26 - 01:42] Process.env is an object within process that contains information representative of the state of the Node environment. During runtime, the reference to an environment variable here is replaced with the actual value of the variable.

    [01:43 - 02:07] Environment variables defined within process can be specified both in a development setting as well as in a production setting. Though there are different ways to introduce environment variables to an application and it can actually be a pretty broad topic, we're going to go through a very simple approach of introducing these environment variables in our development environment.

    [02:08 - 02:21] We'll use the .env library, which is a popular package that helps load variables from a .env file in Node.js project. This is helpful during development.

    [02:22 - 02:35] So the first thing we'll do is head to the terminal and install the .env library as a development dependency. We'll also install the type declaration file of .env as a development dependency as well.

    [02:36 - 02:56] Now, as a note, we're installing .env as a development dependency since when we deploy our app, our cloud management solution, Heroku, will automatically save our environment variables into process.env. As a result, we don't need the .env library in our production code.

    [02:57 - 03:14] However, if you choose to use a northern method to deploy your app that may require a .env file, you might need to install .env as a regular dependency. This is totally dependent in how you attempt to have your environment variables be defined in a production setting.

    [03:15 - 03:32] With .env installed, we'll go ahead and create a .env file in the root of our project directory. In this .env file, we can specify the different values we'd want to pass in as environment variables.

    [03:33 - 03:45] Convention often finds us defining these variables with capital letters. We'll define the database user, database user password, and database cluster variables.

    [03:46 - 04:02] In certain production environments like Heroku, for example, we can specify the port in which the app is to run as an environment variable as well. So with that said, we'll also specify a port variable, which will be the port our app is to run on.

    [04:03 - 04:18] We'll then apply the values to these variables. We'll get the database values from our Mongo Atlas dashboard, and then we'll specify for our development environment a value of 9,000 for the port environment variable.

    [04:19 - 04:38] Next, we'll modify our code to use the values from our .env file. First, we'll go to the index file in our source folder, and we'll require and configure the .env library as early as possible in our application.

    [04:39 - 04:58] To do so, before any of the imports, we'll use the require syntax to introduce the library and run the config function right after. This right here helps us avoid any ES lint warnings of running code before the import of other files.

    [04:59 - 05:18] And by doing so as early as possible, this helps prevent any compilation issues that can come up, where other imported files don't pick up any environment variables. Process.env will now have the keys and values defined from our .env file when we run our application in development.

    [05:19 - 05:41] So in our app.listen function and the console log function in our source index file, we'll pass in a value of process.env.ports to reference the port environment variable in our .env file. We'll also remove the pre-existing port variable we had in this file.

    [05:42 - 05:59] In our database index file, we'll reference the values necessary for our Mongo DB connection from process.env. We'll also remove the hard coded variables we've specified before.

    [06:00 - 06:18] Like we've mentioned before, environment variables should never be committed to source code. An easy way to prevent Git from committing the entire .env file is by introducing a .gidignore file that references the files we don't want committed .

    [06:19 - 06:43] So we'll go ahead and create a .gidignore file at the roots of our project directory. In addition to not ever committing .env files, there's a few other files and folders that usually don't necessarily need to be committed, such as the node modules folder and the build folder from our TypeScript compilation process.

    [06:44 - 06:57] This is because these particular folders can always be regenerated from the user downloading our projects. We can also prevent the committing of any NPM or Yarn debug logs.

    [06:58 - 07:14] So with that said, we'll paste the series of files and folders we think shouldn 't be committed here, but you're more than welcome to customize this as you see fit. We'll also provide the content of this particular file in our lesson documentation.

    [07:15 - 07:35] Okay, now will be a good time to verify that everything still works. We'll go back to the source index file and let's quickly bring back the listings fine check we had before to verify if you were able to retrieve information from our sample listings collection in the database.

    [07:36 - 07:52] We'll then head to the terminal and start our server. We see the port number be logged in our console in addition to the sample listing data be presented from our Mongo database.

    [07:53 - 08:07] This tells us the environment variables we've set up work as intended. [ Silence ]