Use Env variable with ZOD for NodeJS and reacted
Environment variables are vital for configuring applications, whether it’s for backend services in Node.js or frontend React apps. However, ensuring these variables are correctly set and valid can be tricky, especially when working across multiple environments like development, staging, and production.
This article will guide you through how to set up and validate environment variables in Node.js and React using Zod, a powerful schema validation library.
Part 1: Using Zod with Environment Variables in Node.js
Install the Required Packages
First, install zod and dotenv in your Node.js project:
npm install zod dotenv
2. Setting Up Your .env File
In the root of your project, create a .env file to store your environment variables:
PORT=3000
DATABASE_URL=mongodb://localhost:27017/mydb
NODE_ENV=development
3. Validating Environment Variables with Zod in Node.js
Here’s how you can load and validate your environment variables:
import { z } from 'zod';
import dotenv from 'dotenv';
// Load .env file
dotenv.config();
// Define the schema for environment variables
const envSchema = z.object({
PORT: z.string().nonempty().transform(Number),
DATABASE_URL: z.string().url(),
NODE_ENV: z.enum(['development', 'production', 'test']),
});
// Parse and validate the environment variables
const envVars = envSchema.safeParse(process.env);
if (!envVars.success) {
. console.error('Invalid environment variables:', envVars.error.format());
. process.exit(1);
}
const { PORT, DATABASE_URL, NODE_ENV } = envVars.data;
console.log(`Server running on port ${PORT}`);
console.log(`Database connected to ${DATABASE_URL}`);
console.log(`Environment: ${NODE_ENV}`);
Explanation:
• Validation with Zod ensures that the environment variables are correctly typed.
• If validation fails, the application will exit, preventing incorrect configurations from breaking the app.
Optional Variables and Defaults
If you have optional variables or want to set default values:
const envSchema = z.object({
PORT: z.string().nonempty().transform(Number).default(3000),
DATABASE_URL: z.string().url(),
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
});
Part 2: Using zod with Environment Variables in React
Now, let’s move on to how this setup would look in a React application.
React apps can also benefit from validating environment variables. While dotenv is used at build time for a React app, you can still use zod to validate your variables, ensuring your app has the correct configuration at runtime.
Setting Up Environment Variables in React
In a React project, environment variables must be prefixed with REACT_APP_. Here’s an example .env file for React:
REACT_APP_API_URL=https://api.example.com
REACT_APP_VERSION=1.0.0
REACT_APP_ENV=development
2. Using Zod for Validation in React
Since React doesn’t use dotenv at runtime, you’ll validate the variables that are available globally via process.env in a React app. Here’s how you can validate environment variables in a React application using zod.
3. Validating React Environment Variables Using zod
In a React app, you’ll need to use the environment variables available through process.env directly. You can create a custom validation utility that runs when the application starts to ensure all required variables are available and valid.
Here’s how you can validate the environment variables in a React app:
import { z } from 'zod';
// Define the schema for the environment variables
const envSchema = z.object({
REACT_APP_API_URL: z.string().url(), // Ensure it's a valid URL
REACT_APP_VERSION: z.string().nonempty(), // Ensure it's a non-empty string
REACT_APP_ENV: z.enum(['development', 'production', 'test']), // Restrict to allowed values
});
// Validate the environment variables
const envVars = envSchema.safeParse(process.env);
if (!envVars.success) {
. // Handle validation errors by logging them
. console.error('Invalid environment variables:', envVars.error.format());
. throw new Error('Invalid environment variables');
}
const { REACT_APP_API_URL, REACT_APP_VERSION, REACT_APP_ENV } = envVars.data;
console.log(`API URL: ${REACT_APP_API_URL}`);
console.log(`App Version: ${REACT_APP_VERSION}`);
console.log(`Environment: ${REACT_APP_ENV}`);
Explanation:
• Schema Definition: Just like in Node.js, you define the structure and constraints of each environment variable using zod.
• Validation: When the app initializes, it runs the validation on the process.env variables that start with REACT_APP_. If any variables are missing or invalid, it throws an error and logs detailed messages to the console.
• Error Handling: If any validation fails, the app throws an error early, which can prevent misconfigurations from causing issues later in the app.
4. Using the Validated Variables in React Components
Once validated, you can use the environment variables across your React components. Here’s an example of using them in a component:
import React from ‘react’;
function App() {
return (
<div>
<h1>Welcome to the App</h1>
<p>API URL: {process.env.REACT_APP_API_URL}</p>
<p>Version: {process.env.REACT_APP_VERSION}</p>
<p>Environment: {process.env.REACT_APP_ENV}</p>
</div>
);
}
export default App;
In this example, the variables are safely accessed after validation, ensuring they are correctly set before being used in the app.
5. Validating Optional Variables and Setting Defaults
Just like in Node.js, you might want to mark some variables as optional or set default values in case they are not provided:
const envSchema = z.object({
REACT_APP_API_URL: z.string().url(),
REACT_APP_VERSION: z.string().nonempty(),
REACT_APP_ENV: z.enum(['development', 'production', 'test']).default('development'),
REACT_APP_FEATURE_FLAG: z.string().optional(), // Optional variable
});
If REACT_APP_FEATURE_FLAG is not set, the application will continue without throwing an error, making it flexible for optional configurations.
Part 3: Common Pitfalls and Best Practices
Prefixing Variables Correctly
In React, remember to prefix all environment variables with REACT_APP_. This is required by Create React App to expose them to the app at build time.
2. Securely Managing Sensitive Variables
Avoid storing sensitive data (like API keys or tokens) directly in environment variables in React, as they are included in the bundle at build time and exposed in the browser. Instead, handle sensitive data on the server side.
3. Ensuring Consistency Between Environments
Use .env, .env.development, .env.production, and .env.test (you can also configure your custom env vars) files to keep environment-specific configurations separate. Make sure to validate each environment to avoid inconsistencies between development, staging, and production.
4. Fail Fast
By validating your environment variables with zod, your application can “fail fast,” meaning it will stop running if critical configuration issues are found early, preventing runtime errors later on.
Conclusion
Using Zod to validate environment variables helps ensure that your application starts with the correct configuration and avoids hard-to-debug runtime errors. Whether you’re working with a Node.js backend or a React frontend, you can enforce validation, provide defaults, and ensure consistency across different environments.
By validating variables early, you reduce the risk of misconfigurations and can easily handle errors before they impact your application. With zod’s type-safe schema validation, you get a clear and structured way to manage environment variables.
I hope you learn something new :)
Best Regards,
Chen.R