
Managing Multiple Local Environments in a Next.js Project
Introduction
When developing the frontend for pepy.tech, we faced a challenge: needing multiple local development environments. Specifically, we wanted the flexibility to toggle between pointing to the live pepy.tech domain and a local backend server. While Next.js offers built-in environment variable handling, its default configuration fell short and limited for our use case. Here’s how we solved it (and the trade-offs we encountered).
The Problem: Next.js Environment File Limitations
Next.js natively supports environment files with the following priority order:
process.env
(directly injected variables).env.$(NODE_ENV).local
(e.g., .env.development.local).env.local
(ignored in test environments).env.$(NODE_ENV)
(e.g., .env.production).env
This structure works well for basic setups, but we needed two distinct local environments:
- Local Backend: Connect our local frontend to a backend running on localhost.
- Live: Connect our local frontend to the production pepy.tech API.
The default Next.js setup doesn’t allow custom environment "profiles" beyond development, test, and production. Creating a .env.local_server
file, for example, isn’t natively recognized.
The Solution: Leveraging env-cmd
To bypass this limitation, we used the env-cmd package. This tool lets you specify a custom .env
file when running commands.
Here’s how we implemented it:
Step 1: Create a Custom Environment File
Add a .env.local_server
file with variables specific to your local server (e.g., API endpoints):
NEXT_PUBLIC_API_URL=http://localhost:8000
Step 2: Update package.json Scripts
Modify your scripts to include a dedicated command for the local server environment:
{
"scripts": {
"dev": "next dev", // Uses default .env.development
"dev:local": "env-cmd -f .env.local_server next dev"
}
}
How It Works
- Running
npm run dev:local
loads variables from.env.local_server
first, followed by Next.js’s default hierarchy. - The
env-cmd
tool injects your custom variables intoprocess.env
, ensuring they take precedence over other .env files.
Key benefits
- No Code Changes Required: Switch environments by running dev or dev:local.
- Clean Separation: Keep live and local configurations isolated.
- Flexibility: Easily add more environments (e.g., dev:staging) with new .env files.
The Catch: Hot Reload Limitations
While this approach works, we noticed one downside: changes to .env.local_server
don’t trigger hot reloads. To apply new values, you’ll need to:
- Stop the dev server (
Ctrl + C
). - Restart it with
npm run dev:local
.
This occurs because env-cmd
loads the file once at startup, unlike Next.js’s built-in environment handling, which watches .env files.
Conclusion
For projects requiring multiple local environments, env-cmd
offers a simple yet powerful workaround.
While the hot reload limitation adds a minor inconvenience, the benefits of clean environment separation far outweigh the drawback.
Alternatives to Explore:
- Use a library like
dotenv
with a customNODE_ENV
value. - Dynamically load environment variables at runtime (though this may impact performance).
Have you tackled this problem differently? Share your approach in the comments!
Final Tip: Always add .env*.local to your .gitignore to avoid exposing secrets!
Happy coding! 🚀