DEV Community

Hasan Zohdy
Hasan Zohdy

Posted on

29-Nodejs Course 2023: Working With Dot Env (.env)

Pro Tip

While you're in the development cycle in a project in daily basis, its always recommended to start your project by checking for updates for the packages that yuo use in your project. This is because the packages that you use in your project are maintained by the community and they are updated frequently.

Why would i do this? for multiple reasons actually, to make sure you're as a developer not outdated person, packages post patches regularly to fix bugs and security issues, and also to make sure that you're using the latest features that are available in the packages that you use.

This step should not be done in a production project unless you have a good reason to do so.

In our project, you'll notice there is a script command called update in the package.json file, this command will run the npm-check-updates package which will check for updates for the packages that we use in our project.

So let's start our day today with it.

yarn update
Enter fullscreen mode Exit fullscreen mode

Dot Env

Now let's talk about Dot Env files (.env), this is a file that contains environment variables that we can use in our project, this file is not tracked by git, so it's safe to put sensitive information in it.

Why do we need it?

We need it to store sensitive information in our project, for example, the database connection string, the port that our server will listen to etc.

Also it will help us to have different configurations for different environments for different developers, for example, we can have a different database connection string for development and production.

And you can set your database connection in your local machine that your fellow developers will have another configurations data for their own.

Installation

Run the following command to install the Dot Env package.

yarn add @mongez/dotenv
Enter fullscreen mode Exit fullscreen mode

Preparation

As we want to use our data that are stored in the .env file in any of our configuration files, we need to load it first at the very beginning of our project.

Open src/core and create bootstrap.ts file, and add the following code.

// src/core/bootstrap.ts
import { loadEnv } from '@mongez/dotenv';

loadEnv();

Enter fullscreen mode Exit fullscreen mode

Now we need to import this file in our src/index.ts file and make sure its at the very beginning of the file.

// src/index.ts
import 'core/bootstrap';
import "app/routes";
import startApplication from "core/application";
import "./config";

startApplication();
Enter fullscreen mode Exit fullscreen mode

If you're using organized imports plugin, make sure to leave an empty line after the import statement so it will disable ordering for it.

Usage

So now we're ready with out setup, one final step is to create .env file in our root directory, if you're walking with me in this series, you will see when we installed the project there shall be a file called .env or .env.example, if you find .env.example file, rename it to .env and open it.

How to use it?

Env files have a key=value format, for example:

DEBUG=true
APP_NAME="My App"
PORT=3000
BAE_URL=localhost #Without the port
Enter fullscreen mode Exit fullscreen mode

Now we added three variables, DEBUG, APP_NAME and PORT.

You can read more about DotEnv Package on Github.

Accessing the variables

There are two ways to access these variables, the most common one is by using process.env object, that object is a built in object in Nodejs, and it contains all the environment variables that are set in the system.

The other one is by using the env function that we imported from @mongez/dotenv package.

import { env } from '@mongez/dotenv';

// using process.env
const debug = process.env.DEBUG;

// using env function
const debug = env('DEBUG');
Enter fullscreen mode Exit fullscreen mode

.env function is more convenient to use, because it has a second parameter that you can pass a default value to it, for example:

import { env } from '@mongez/dotenv';

// using process.env
const debug = process.env.DEBUG || false;

// using env function
const debug = env('DEBUG', false);
Enter fullscreen mode Exit fullscreen mode

A Side Note About Mongez

If you notice i'm using many packages that starts with @mongez these are typically my own packages, if you wondering what does Mongez mean, it's an Arabic word that means The Accelerator, and i named my packages with this name because i want to accelerate the development process for me and other developers.

Back to our project

So now we added three variables, DEBUG, APP_NAME and PORT in our dot env file, now we can use them in our project. let's define a config file in our config directory and name it app.ts.

// src/config/app.ts
import { env } from '@mongez/dotenv';

const appConfigurations = {
    debug: env('DEBUG', false),
    name: env('APP_NAME'),
    port: env('PORT', 3000),
    baseUrl: env('BASE_URL', 'localhost'),
};

export default appConfigurations;
Enter fullscreen mode Exit fullscreen mode

Now let's import our app configuration in our src/config/index.ts file.

// src/config/index.ts
import appConfigurations from './app';
import config from "@mongez/config";
import databaseConfigurations from "config/database";
import validationConfigurations from "./validation";

config.set({
  database: databaseConfigurations,
  validation: validationConfigurations,
  app: appConfigurations,
});
Enter fullscreen mode Exit fullscreen mode

If you notice here we used the variables from .env file in our app.ts file so we can keep all of the application configuration in one place, thus we won't use it in our code directly.

Moving Connect To Server

We added a function called connectToServer in our http index file, let's move it to a file to make it more organized.

Just rename the index.ts file to connectToServer.ts then create an index file with the following code:

// src/http/index.ts
export { default as connectToServer } from './connectToServer';
Enter fullscreen mode Exit fullscreen mode

Now head to src/core/application.ts and update the import statement.

// src/core/application.ts
import { connectToServer } from "core/http";

// ...
Enter fullscreen mode Exit fullscreen mode

Updating Server Configurations

Now let's update the src/http/connectToServer.ts file to use the configurations from our app configurations

// src/http/connectToServer.ts
import config from '@mongez/config';
import multipart from "@fastify/multipart";
import router from "core/router";
import Fastify from "fastify";

export default async function connectToServer() {
  const server = Fastify();

  server.register(multipart, {
    attachFieldsToBody: true,
  });

  router.scan(server);

  try {
    // πŸ‘‡πŸ» We can use the url of the server
    const address = await server.listen({ port: config.get('app.port'), host: config.get('app.baseUrl') });

    console.log(`Start browsing using ${address}`);
  } catch (err) {
    server.log.error(err);
    process.exit(1); // stop the process, exit with error
  }
}
Enter fullscreen mode Exit fullscreen mode

And that's it!

🎨 Conclusion

In this article we learned about dot env files, why they are important and how to install and use it.

Next, we're going back to our database section, we'll start working with Models!

🎨 Project Repository

You can find the latest updates of this project on Github

😍 Join our community

Join our community on Discord to get help and support (Node Js 2023 Channel).

🎞️ Video Course (Arabic Voice)

If you want to learn this course in video format, you can find it on Youtube, the course is in Arabic language.

πŸ’° Bonus Content πŸ’°

You may have a look at these articles, it will definitely boost your knowledge and productivity.

General Topics

Packages & Libraries

React Js Packages

Courses (Articles)

Latest comments (0)

11 Tips That Make You a Better Typescript Programmer

typescript

1 Think in {Set}

Type is an everyday concept to programmers, but it’s surprisingly difficult to define it succinctly. I find it helpful to use Set as a conceptual model instead.

#2 Understand declared type and narrowed type

One extremely powerful typescript feature is automatic type narrowing based on control flow. This means a variable has two types associated with it at any specific point of code location: a declaration type and a narrowed type.

#3 Use discriminated union instead of optional fields

...

Read the whole post now!