Skip to content

Commit

Permalink
Add blog post on node 20.6+ built in .env support
Browse files Browse the repository at this point in the history
  • Loading branch information
motdotla committed Oct 29, 2023
1 parent 31e5106 commit 69d2363
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 8 deletions.
6 changes: 6 additions & 0 deletions _includes/components/note.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<div class="my-6 flex gap-2.5 rounded-2xl border border-emerald-500/20 bg-emerald-50/50 p-4 leading-6 text-emerald-900 dark:border-emerald-500/30 dark:bg-emerald-500/5 dark:text-emerald-200 dark:[--tw-prose-links-hover:theme(colors.emerald.300)] dark:[--tw-prose-links:theme(colors.white)]">
<svg viewBox="0 0 16 16" aria-hidden="true" class="mt-1 h-4 w-4 flex-none fill-emerald-500 stroke-white dark:fill-emerald-200/20 dark:stroke-emerald-200"><circle cx="8" cy="8" r="8" stroke-width="0"></circle><path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6.75 7.75h1.5v3.5"></path><circle cx="8" cy="4" r=".5" fill="none"></circle></svg>
<div class="[&amp;>:first-child]:mt-0 [&amp;>:last-child]:mb-0">
<p>Find a complete <a href="{{include.url}}">code example on GitHub</a> for this blog post.</p>
</div>
</div>
4 changes: 2 additions & 2 deletions assets/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ layout: null
@apply dark:text-zinc-100;
}
.prose img {
@apply rounded-lg border-zinc-800;
@apply rounded-lg border border-zinc-200 dark:border-zinc-800 shadow-sm;
}

hr {
@apply border-zinc-100 dark:border-zinc-800;
@apply border border-zinc-100 dark:border-zinc-800;
}

.changelog h2 {
Expand Down
Binary file added assets/img/blog/dotenv-vault-screenshot2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/blog/node-env-file-support.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions blog/_posts/2023-03-13-how-to-use-dotenv.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ Great! You just used dotenv at its foundational layer!

---

### dotenv-vault — A secrets manager for .env and .env.vault files.
### Using `.env` files?

<img src="/assets/img/blog/dotenv-vault-screenshot.png" />
[dotenv-vault](https://github.com/dotenv-org/dotenv-vault) is a secrets manager for securely managing them. [Create your Dotenv Account](https://dotenv.org) and try it today.

If you are looking to backup and manage your `.env` files across multiple projects, a larger team, complete with permissions, versions, and history then create a [Dotenv Account](https://dotenv.org). It's free with premium features.
<img src="/assets/img/blog/dotenv-vault-screenshot2.png" />

[https://dotenv.org/signup](https://dotenv.org/signup)
6 changes: 4 additions & 2 deletions blog/_posts/2023-10-24-what-is-env-vault-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ It's an encrypted copy of your `.env` files.

It is easiest to understand if you generate one. So let's do that. Then I'll show you how to use it in production. Lastly, we'll talk about its security advantages.

{% include components/note.html url="https://github.com/dotenv-org/examples/tree/master/dotenv-blog/2023-10-24" %}

## Generating

We're going to use the command `npx dotenv-vault local build`.
Expand All @@ -21,7 +23,7 @@ We're going to use the command `npx dotenv-vault local build`.

Enter a project where you already have `.env.*` file(s) and have installed [dotenv](https://github.com/motdotla/dotenv).

For example, I have a project with 3 files in it. See [example code](https://github.com/dotenv-org/examples/tree/master/dotenv-blog/what-is-env-vault-file).
For example, I have a project with 3 files in it.

* index.js
* .env
Expand Down Expand Up @@ -151,7 +153,7 @@ I'd encourage you to give `.env.vault` files a try. I think you will like them a

### dotenv-vault — A secrets manager for .env and .env.vault files.

<img src="/assets/img/blog/dotenv-vault-screenshot.png" />
<img src="/assets/img/blog/dotenv-vault-screenshot2.png" />

If you are looking to also manage your `.env` and `.env.vault` files across a larger team, complete with permissions, versions, and history then create a [Dotenv Account](https://dotenv.org). It's free with premium features.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
---
layout: blog
author: mot
title: "Node.js 20.6.0 includes built-in support for .env files"
image: "/assets/img/blog/node-env-file-support.png"
excerpt: "Node v20.6.0+ adds native support for loading .env files."
published: true
---

Node v20.6.0+ adds native support for loading `.env` files.

```
node --env-file=.env index.js
```

Wow, cool!

Is [dotenv](https://github.com/motdotla/dotenv) [dead](https://francoisbest.com/posts/2023/dotenv-is-dead?ref=dailydev)? [Stop using it](https://medium.com/@tony.infisical/stop-using-dotenv-in-node-js-v20-6-0-8febf98f6314)? Not so fast. **Don't drop dotenv** just yet. There are some caveats you should know first.

First, let me say, it is great to see the NodeJS team adopt first-class `.env` support for developers. As [one of the pioneers of dotenv](https://github.com/motdotla/dotenv/graphs/contributors), it's an honor. **dotenv** is depended on by more than [14 Million](https://github.com/motdotla/dotenv/network/dependents) open source repos on GitHub alone and downloaded more than [35 Million](https://www.npmjs.com/package/dotenv) times per week. [dotenv](https://github.com/motdotla/dotenv) has proven itself as a trusty friend to millions of developers worldwide.

Anyways, let's see how this built-in support works (or [skip to the caveats](#caveats) section).

{% include components/note.html url="https://github.com/dotenv-org/examples/tree/master/dotenv-blog/2023-10-28" %}

## How it works

Install Node v20.6.0 or greater using [nvm](https://github.com/nvm-sh/nvm).

```
nvm install 20.6.0
nvm use 20.6.0
node -v
v20.6.0
```

Create your `.env` file.

```
HELLO="World"
````

Create your node script to make use of it.

```
// index.js
console.log(`Hello ${process.env.HELLO}`)
```

Run it with the `--env-file` flag.

```
node --env-file=.env index.js
Hello World
```

That's it!

Want to run it in production? Just point it to a `.env.production` file.

```
# .env.production
HELLO="production"
```

```
node --env-file=.env.production index.js
```

## Caveats

The biggest *current* caveat is that this is still an experimental feature. That means it will ship with [bugs](https://github.com/nodejs/node/pull/49424#issue-1876566254) and with [missing feature support](https://github.com/nodejs/node/issues/49148). The [top hn comment](https://news.ycombinator.com/item?id=37174916) sums it up well - albeit a bit grumpily.

<img src="/assets/img/blog/hacker-news-node-dotenv-support.png" />

I also want stress the word *current* because this is all still under active development. These things take time. By the time you read this, some of these caveats might no longer be around.

### Missing multiline support

The current implementation does not support multiline environment variables. If you attempt to include a multiline environment variable it will be `undefined`. For example:

```
# .env.multiline
HELLO="This
is
a
multiline"
```
```
// index.js
console.log(`Hello ${process.env.HELLO}`)
```
```
node --env-file=.env.multiline index.js
Hello undefined
```

Note: multiline support is being actively discussed and will probably get added in the near future.

### Missing override option

You cannot override your system's environment variables with your `.env` file. There is no option.

```
# .env
HELLO="World"
```
```
// index.js
console.log(`Hello ${process.env.HELLO}`)
```
```
export HELLO="System"
node --env-file=.env index.js
Hello System
```

It prints `Hello System` rather then `Hello World`. There is no option to overwrite system variables.

If you need to do this then continue using dotenv with [its override option](https://github.com/motdotla/dotenv#override).

### Missing variable expansion

It's important to note that variable expansion support has always existed in a separate library [dotenv-expand](https://github.com/motdotla/dotenv-expand). But it is so [widely used with 13 million downloads](https://www.npmjs.com/package/dotenv-expand) that it defacto considered part of dotenv.

As of this writing, Node does not support variable expansion. Instead, it will output the variable as a string.

```
# .env
PASSWORD="password123"
SECRET=$PASSWORD
```
```
// index.js
console.log(`The secret is ${process.env.SECRET}`)
```
```
node --env-file=.env index.js
The secret is $PASSWORD
```

So if you need variable expansion, you should continue using [dotenv](https://github.com/motdotla/dotenv) and [dotenv-expand](https://github.com/motdotla/dotenv-expand).

### Missing `.env.vault` support

The `.env.vault` file is the spiritual successor to the `.env` file. They have multiple security advantages which you can [read about here](https://www.dotenv.org/blog/2023/10/24/what-is-env-vault-file.html).

They are [quite new](https://github.com/motdotla/dotenv/pull/730) but also quite useful for production and ci. They are gaining adoption across multiple languages like [python](https://github.com/dotenv-org/python-dotenv-vault) and [rust](https://docs.rs/dotenv-vault/latest/dotenv_vault/). [dotenv](https://github.com/motdotla/dotenv) supports them but Node's implementation of `.env` files does not at this time.

```
#/-------------------.env.vault---------------------/
#/ cloud-agnostic vaulting standard /
#/ [how it works](https://dotenv.org/env-vault) /
#/--------------------------------------------------/
# development
DOTENV_VAULT_DEVELOPMENT="AtEC33ZfFJQMSE6C+EBX8nzTyQzfC+xhsIfGjyWr47jiHsUi07PHzX2/RmCB0PIi"
# production
DOTENV_VAULT_PRODUCTION="t9van8HefnTIHVlK3vQ6WYLtWEOvPunEnOphV3Hw3aBTBDuwLq22yU0Tdl5fAnk="
```

## Conclusion

In conclusion, built-in support for `.env` files (even if currently experimental) is a huge and welcome step forward for Node. We should particularly thank Yagiz Nizipli for making this happen. [Go sponsor him on GitHub](https://github.com/sponsors/anonrig). He is doing incredible work for Node.

That said, there are some caveats, and I would recommend against npm uninstall-ing dotenv for your production apps at this time. Wait until it is non-experimental and has added support for the missing features above.

---

### Using `.env` files?

[dotenv-vault](https://github.com/dotenv-org/dotenv-vault) is a secrets manager for securely managing them. [Create your Dotenv Account](https://dotenv.org) and try it today.

<img src="/assets/img/blog/dotenv-vault-screenshot2.png" />

[https://dotenv.org/signup](https://dotenv.org/signup)
2 changes: 1 addition & 1 deletion blog/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: "Blog"
<li class="col-span-full">
<a href="{{ post.url }}">
<div class="space-y-2 md:grid md:grid-cols-3 md:gap-4">
<img alt="{{ post.title }}" loading="lazy" width="395" height="208" decoding="async" class="col-span-2 w-full object-cover rounded lg:rounded-md border border-zinc-800" style="color:transparent" src="{{ post.image }}">
<img alt="{{ post.title }}" loading="lazy" width="395" height="208" decoding="async" class="col-span-2 w-full object-cover rounded lg:rounded-md border border-zinc-50 dark:border-zinc-700 shadow-sm" style="color:transparent" src="{{ post.image }}">

<div class="mt-2 lg:mt-0">

Expand Down

0 comments on commit 69d2363

Please sign in to comment.