Setting the Stage: Why Environment Variables Matter
Environment variables are a fundamental part of modern software development. They allow you to configure your application’s behavior without modifying its code. This is crucial for several reasons:
- Configuration Flexibility: Different environments (development, testing, production) often require different settings (database connections, API keys, feature flags). Environment variables provide a clean way to manage these differences.
- Security: Sensitive information, like API keys or database passwords, should never be hardcoded into your application. Instead, store them as environment variables.
- Portability: Applications become more portable when configuration is separated from code.
This tutorial focuses on how to effectively manage environment variables directly within your project’s package.json
file, leveraging npm scripts.
Defining Environment Variables in npm Scripts
npm scripts, defined within the "scripts"
section of package.json
, provide a convenient way to automate tasks. You can seamlessly incorporate environment variable settings into these scripts.
The basic approach is to prefix your script command with the environment variable assignment.
For macOS and Linux:
{
"name": "my-app",
"version": "1.0.0",
"scripts": {
"start": "NODE_ENV=production node app.js",
"test": "NODE_ENV=test mocha --reporter spec"
}
}
In this example:
NODE_ENV=production node app.js
sets theNODE_ENV
environment variable to "production" before executingnode app.js
.NODE_ENV=test mocha --reporter spec
similarly setsNODE_ENV
to "test" before running your tests.
Your application code can then access these variables using process.env.NODE_ENV
.
Important Note for Windows:
The approach above does not work natively on Windows. Windows requires a different syntax:
{
"name": "my-app",
"version": "1.0.0",
"scripts": {
"start": "set NODE_ENV=production && node app.js",
"test": "set NODE_ENV=test && mocha --reporter spec"
}
}
Notice the use of set
and &&
instead of a simple assignment. set
is the Windows command for setting environment variables, and &&
ensures that the node
command only executes if the set
command is successful.
Cross-Platform Compatibility with cross-env
The need for different syntax on Windows and macOS/Linux can be cumbersome. Fortunately, the cross-env
package provides a solution for cross-platform compatibility.
-
Installation:
npm install --save-dev cross-env
-
Usage:
{ "name": "my-app", "version": "1.0.0", "scripts": { "build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js", "start": "cross-env NODE_ENV=development node app.js" } }
cross-env
automatically handles the correct syntax for setting environment variables on the current operating system. This simplifies your package.json
and makes your project more portable. It essentially acts as a wrapper, ensuring consistent behavior across platforms.
Using .env
Files for More Complex Configuration
For projects with many environment variables, managing them directly in package.json
can become unwieldy. A common practice is to store them in a .env
file (make sure to add .env
to your .gitignore
to avoid committing sensitive information to version control).
Example .env
file:
VAR_A=Hello World
VAR_B=format the .env file like this with new vars separated by a line break
Then, within your package.json
, you can use a script to load these variables before starting your application:
{
"name": "my-app",
"version": "1.0.0",
"scripts": {
"start": "export $(cat .env | xargs) && node index.js",
"env-linux": "export $(cat .env | xargs) && env",
"start-linux": "export $(cat .env | xargs) && npm start",
"env-windows": "(for /F \"tokens=*\" %i in (.env) do set %i)",
"start-windows": "(for /F \"tokens=*\" %i in (.env) do set %i) && npm start"
}
}
This approach requires different commands for Linux and Windows, but allows you to keep a centralized configuration file.
Accessing Environment Variables in Your Code
Once the environment variables are set, you can access them within your JavaScript code using process.env
:
const nodeEnv = process.env.NODE_ENV;
const apiKey = process.env.API_KEY;
console.log(`Running in ${nodeEnv} mode`);
console.log(`API Key: ${apiKey}`);
Best Practices
- Never commit sensitive information (API keys, passwords) to your version control system. Use environment variables and
.gitignore
to protect this data. - Keep your
.env
file separate from your codebase. - Use
cross-env
for cross-platform compatibility. - Consider using a dedicated environment variable management tool for larger projects.