Accessing .env files natively with Node.js
Tags: node, javascript, development
Published: 2023-11-28 20:08:59

---
title: Accessing .env files natively with Node.js
published: true
tags: nodejs,javascript,development
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ns3hf3ol7pyftlmhb7er.png
---

Starting the week with incredible news and one of the most awaited new features of Node.js in years, the **native** support for the use of environment files, the so-called **dotenvs** or **env-config**.

## dotenv

One of the most common and widely used packages in the JavaScript community is the [dotenv](https://npm.im/dotenv?ref=blog.lsantos.dev) package. It does something super simple, but at the same time essential: it loads environment variables into the runtime memory.

Environment variables are special variables that carry protected data that cannot be exposed in the code and are only available in the environment in which they are inserted, for example, a VM or a serverless function.
I've written a lot about them [in this article](https://imasters.com.br/desenvolvimento/protegendo-seus-dados-utilizando-variaveis-de-ambiente?ref=blog.lsantos.dev) - including using the old way of loading variables, with `dotenv`, so it's nice to have a look at how Node has evolved since then - but, essentially, environment variables are the ideal place to store database users and passwords, or even token secrets, since, in order to access and fetch this data, the application needs to have access to the same machine and the same host, which is much more difficult than having access only to the code.

These variables are stored in files we call `dotenv`, or `.env`, which are files defined in `INI` or `bash` format depending on the runtime you are using (for dotenv it would be INI), so an environment file could look like this:

```ini
PASSWORD=123
USER=123
```

However, we had always needed a module to be able to load these variables, until Deno arrived.

### Deno

Deno has greatly changed the way runtimes look at these files because it allows you to load them directly from your [standard library](https://deno.land/std@0.203.0/dotenv/mod.ts?ref=blog.lsantos.dev). In other words, instead of having to install a separate module, we can use what is native to the runtime:

```ts
// app.ts
import { load } from "https://deno.land/std@0.203.0/dotenv/mod.ts";

console.log(await load({export: true})); // { GREETING: "hello world" }
console.log(Deno.env.get("GREETING")); // hello world
```

## Node 20

Node 20.6 brings [a change](https://nodejs.org/en/blog/release/v20.6.0?ref=blog.lsantos.dev#built-in-env-file-support) that goes beyond what Deno has already done, **now it's possible to read .env files directly from the runtime**.

Instead of having to do:

```ts
require('dotenv').config()
const {DB_HOST, DB_PORT, DB_USER, DB_PASS} = process.env
const db = require('some-database-lib')

db.connect({
    host: DB_HOST,
    port: DB_PORT,
    user: DB_USER,
    pass: DB_PASS
})
```

We can simply use the command `node --env-file=<path> index.js` and all the variables present in our file defined in the path will be loaded into our `process.env`. For example, imagine a `.env` file as follows:

```ini
DB_PASS=pass
DB_USER=root
DB_PORT=5432
DB_HOST=localhost
```

When we run our Node with the command `node --env-file=.env index.js`, we can use the variable `process.env.DB_PASS`, and it will have the value of `pass`, just like the other variables that will be perfectly set in our application for use.

But that's not the only new feature.

### Node options

Node.js allows you to create an environment variable called `NODE_OPTIONS`, it allows you to set all the options that would be passed to node in the main command directly in the variable, that is, if we want, for example, to start Node with an inspector (using the `--inspect` flag) we can use: `NODE_OPTIONS='--inspect'` and now all executions of `node index.js` will be as if they were written `node --inspect index.js`.

There used to be a way to leave these settings in `package.json`, but envs support changes everything, so now you can leave the Node options (except, of course, the `--env-file` itself) in an environment variable:

```ini
NODE_OPTIONS='--inspect --loader=tsx'
```

As I showed in [my article on TSX](https://dev.to/_staticvoid/how-to-run-typescript-natively-in-nodejs-with-tsx-3a0c), we can load TypeScript files natively using a loader, and on top of that we can load our environment file directly, with the command above we can run `node --env-file=.env index.ts`, for example.

# Conclusion

This feature is huge! While it removes a package from our list of dependencies, it still allows us to make our code simpler and more straightforward but remember that it is only available from version **20.6** on.