A no-dependency JavaScript port of dotenv-java, itself a port of the Ruby dotenv project. Load environment variables from a .env file.
Why dotenv?
Storing configuration in the environment is one of the tenets of a twelve-factor app. Anything that is likely to change between deployment environments–such as resource handles for databases or credentials for external services–should be extracted from the code into environment variables.
But it is not always practical to set environment variables on development machines or continuous integration servers where multiple projects are run. Dotenv load variables from a .env file into ENV when the environment is bootstrapped.
Environment variables listed in the host environment override those in .env.
Use dotenv.get("...") instead of process.env[...].
Requires Node 18 or greater.
npm install dotenv-jsCreate a .env file in the root of your project
# formatted as key=value
MY_ENV_VAR1=some_value
MY_EVV_VAR2=some_value #some value comment
MULTI_LINE="some
multi line
value"import { Dotenv } from "dotenv-js";
const dotenv = Dotenv.load();
dotenv.get("MY_ENV_VAR1");Configure dotenv-js once in your application.
const dotenv = Dotenv.configure()
.directory("./some/path")
.ignoreIfMalformed()
.ignoreIfMissing()
.load();| Option | Behavior |
|---|---|
directory(path) |
the directory containing the .env file. Default ./ |
filename(name) |
the file name. Default .env |
ignoreIfMalformed() |
skip malformed entries instead of throwing |
ignoreIfMissing() |
return an empty environment instead of throwing when the file is absent |
systemProperties() |
copy each entry into the system property table (see below) |
dotenv.entries(); // host environment + .env
dotenv.entries(Dotenv.Filter.DECLARED_IN_ENV_FILE); // .env only
dotenv.get("KEY"); // null when absent
dotenv.get("KEY", "default value");entries() returns a Set of DotenvEntry. It is unmodifiable: add, delete
and clear throw UnsupportedOperationError.
| dotenv-java | dotenv-js |
|---|---|
Dotenv.configure() / Dotenv.load() |
same, static on Dotenv |
Dotenv.Filter.DECLARED_IN_ENV_FILE |
same |
entries() / entries(filter) |
entries(filter?) |
get(key) / get(key, defaultValue) |
get(key, defaultValue?) |
DotenvEntry#getKey() / #getValue() |
same, plus key / value getters |
DotenvException |
same, with addSuppressed / getSuppressed |
System.setProperty via systemProperties() |
setProperty / getProperty / clearProperty from dotenv-js |
| classpath lookup | resource roots — addClasspathRoot(), setClasspathRoots(), DOTENV_CLASSPATH |
Collections.unmodifiableSet |
UnmodifiableSet, throwing UnsupportedOperationError |
The grammar, the precedence rules, the malformed-entry handling and the exception messages are identical; the port is verified by diffing what both implementations produce for the same fixtures. Three JVM concepts have no direct Node equivalent:
- System properties.
System.setPropertywrites to a table separate from the host environment, whichprocess.envis not.systemProperties()therefore writes to the table exported bysrc/systemProperties.js; read it withgetProperty(key). - Classpath. A
.envthat is not found on the file system is looked up in an ordered list of resource roots — the analogue of a classpath lookup. Roots come fromaddClasspathRoot()/setClasspathRoots()and from theDOTENV_CLASSPATHenvironment variable (delimited likePATH); the working directory is searched last. - Unmodifiable collections.
entries()returns aSetthat throws on mutation rather than aCollections.unmodifiableSet.
java.lang.String#trim, String#substring and Files#readAllLines are
reproduced in src/internal/strings.js rather than approximated with their
JavaScript near-equivalents, which differ on Unicode whitespace and on out of
range indices.
npm testQ: Should I deploy a .env to e.g. production?
A: Tenet III of the 12 factor app methodology states "The twelve-factor app stores config in environment variables". Thus, it is not recommended to provide the .env file to such environments. dotenv, however, is super useful in e.g a local development environment as it enables a developer to manage the environment via a file which is more convenient.
Using dotenv in production would be cheating. This type of usage, however is an anti-pattern.
Q: Why should I use dotenv.get("MY_ENV_VAR") instead of process.env.MY_ENV_VAR
A: dotenv-js does not mutate process.env, so variables listed in .env cannot be retrieved through it. Reading through dotenv.get(...) also applies the host-environment-wins precedence rule.
Q: Can I retrieve environment variables as system properties?
A: Yes. Use the systemProperties option, then read them back with getProperty. Note that this table is deliberately separate from process.env, exactly as the JVM's system properties are separate from the host environment.
Q: Should I have multiple .env files?
A: No. We strongly recommend against having a "main" .env file and an "environment" .env file like .env.test. Your config should vary between deploys, and you should not be sharing values between environments.
In a twelve-factor app, env vars are granular controls, each fully orthogonal to other env vars. They are never grouped together as “environments”, but instead are independently managed for each deploy. This is a model that scales up smoothly as the app naturally expands into more deploys over its lifetime.
– The Twelve-Factor App
Q: Should I commit my .env file?
A: No. We strongly recommend against committing your .env file to version control. It should only include environment-specific values such as database passwords or API keys. Your production database should have a different password than your development database.
Q: What happens to environment variables that were already set?
A: dotenv-js will never modify any environment variables that have already been set. In particular, if there is a variable in your .env file which collides with one that already exists in your environment, then that variable will be skipped. This behavior allows you to override all .env configurations with a machine-specific environment, although it is not recommended.
Q: What about variable expansion in .env?
A: We haven't been presented with a compelling use case for expanding variables and believe it leads to env vars that are not "fully orthogonal" as The Twelve-Factor App outlines. Please open an issue if you have a compelling use case.
Note and reference: The FAQs present on motdotla's dotenv node project page are so well done that I've included those that are relevant in the FAQs above.
see CONTRIBUTING.md
see LICENSE (Apache 2.0)
Thanks goes to these wonderful people (emoji key):
Clement Cherlin 💻 |
Alex Braga 📖 |
Alexey Venderov 💻 |
yassenb 💻 |
Sidney Beekhoven 💻 📖 |
Manoel Campos 💻 |
This project follows the all-contributors specification. Contributions of any kind welcome!

