DEV Community

Cover image for Centralize Your Node.js Config: How to Leverage npm's config Key with cross-env
Ali nazari
Ali nazari

Posted on

Centralize Your Node.js Config: How to Leverage npm's config Key with cross-env

Environment variables are indispensable for configuring applications without hard‑coding sensitive or environment‑specific values.

When working with Node.js and npm scripts, you have several strategies for passing environment variables to your scripts.

In this post, we’ll explore three key approaches:

  1. Using the config key in package.json to store and access custom settings.
  2. Using the cross-env package to set environment variables in a cross‑platform way.
  3. Accessing those settings inside your Node.js application via process.env.

Along the way, we’ll also see how tools like Commitizen leverage the same config key to read values such as the driver for your commit conventions.


Storing Custom Settings with npm config in package.json

npm supports a config section inside package.json, which lets you declare custom configuration keys and default values.

Scripts can access these via npm_package_config_<key> environment variables.

// package.json
{
  "name": "my-app",
  "version": "1.0.0",
  "config": {
    "apiHost": "https://api.example.com",
    "port": "3000"
  },
  "scripts": {
    "start": "node server.js",
    "report": "echo API is at $npm_package_config_apiHost on port $npm_package_config_port"
  }
}
Enter fullscreen mode Exit fullscreen mode

When you run:

npm run report
Enter fullscreen mode Exit fullscreen mode

you’ll see:

API is at https://api.example.com on port 3000
Enter fullscreen mode Exit fullscreen mode

Overriding Config at Runtime

You can override those defaults when invoking npm scripts:

npm run report --apiHost=https://api.staging.local --port=4000
Enter fullscreen mode Exit fullscreen mode

Under the hood, npm maps those flags to the same environment variables (npm_package_config_apiHost, npm_package_config_port).


Setting Environment Variables with cross-env

Unix shells let you write NODE_ENV=production webpack, but Windows CMD and PowerShell use different syntax. To unify across platforms, use cross-env:

npm install --save-dev cross-env
Enter fullscreen mode Exit fullscreen mode

Then in your scripts:

"scripts": {
  "build": "cross-env NODE_ENV=production webpack --config webpack.prod.js",
  "dev":   "cross-env API_URL=$npm_package_config_apiHost PORT=$npm_package_config_port node server.js"
}
Enter fullscreen mode Exit fullscreen mode

Now npm run build and npm run dev work identically on Windows, macOS, and Linux—no syntax changes needed.


Example: Commitizen and the config Key

Commitizen is a tool for standardized commit messages. It reads its adapter (driver) from the config.commitizen.path value in package.json:

// package.json
{
  "config": {
    "commitizen": {
      "path": "./node_modules/cz-conventional-changelog"
    }
  },
  "scripts": {
    "commit": "git-cz"
  }
}
Enter fullscreen mode Exit fullscreen mode

When you run npm run commit (alias for git-cz), Commitizen looks up config.commitizen.path and uses that adapter to guide your commit prompts.


Accessing config Vars Inside Your Node.js App

Once npm has exposed your config values as environment variables, you can read them in any Node.js file using process.env:

// server.js
const express = require('express');
const app = express();

// npm_package_config_port comes from config.port in package.json
const PORT = process.env.npm_package_config_port   || 3000;
const API_URL = process.env.npm_package_config_apiHost || 'http://localhost:4000';

app.get('/', (req, res) => {
  res.send(`API is at ${API_URL}`);
});

app.listen(PORT, () => {
  console.log(`Server listening on port ${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode
  • If you run npm run dev, npm will inject npm_package_config_port and npm_package_config_apiHost for you.
  • If someone runs node server.js directly, the fallback (|| 3000) ensures your app still starts with a sensible default.
  • You can still override at runtime: npm run dev --npm_config_port=5000 will set process.env.npm_package_config_port === '5000'.

5. Best Practices

  • Centralize defaults under config in package.json so scripts and code share the same source of truth.
  • Use cross-env for any script that sets real OS environment variables to guarantee cross‑platform compatibility.
  • Document overrides: show teammates how to tweak via --npm_config_<key>.
  • Leverage in tooling: Commitizen, linters, deploy scripts, etc., all honor the same config block.

By combining npm’s config key, cross-env, and simple process.env access, you get a flexible, DRY, and cross‑platform approach to managing configuration in your Node.js projects.


If you found this helpful, feel free to share

Let’s connect!!: 🤝

LinkedIn
GitHub

Top comments (1)

Collapse
 
nathan_tarbert profile image
Nathan Tarbert

pretty cool, configs always get messy for me and this way actually makes them so much easier to manage
you ever run into issues syncing config between local and CI environments