Reputation: 123
I need to access dotenv variables from within a nested node module using process.env.[VARIABLE].
My file structure looks like this:
root
├── .env
└── server
├── server.js
└── database
├── db.js
└── models.js
inside server.js I load the env config at the beggining of import statements like this:
import dotenv from 'dotenv'
dotenv.config({ path: '../.env' });
console.log(process.env.DB_HOST) //This works as it should
import express from 'express'
import cors from 'cors'
import sequelize from './database/db.js'
import {User} from './database/models.js'
const app = express();
const PORT = process.env.SERVER_PORT || 5000;
// Middleware
app.use(cors());
app.use(express.json());
// Basic health check route
app.get('/api/health', (req, res) => {
res.json({ status: 'Server is running' });
});
// Start the server
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
If I log any of the variables i set up inside .env file from within server.js it works as it should. However if I try to log it from the db.js I get undefined value.
import Sequelize from 'sequelize';
console.log(process.env.DB_HOST) ///returns undefined
console.log(process.env) ///returns the object containing env variables excluding the ones I set in my .env file
const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD, {
host: process.env.DB_HOST,
dialect: 'mysql',
port: process.env.DB_PORT || 3306
});
export default sequelize;
Can anyone tell me what am I doing wrong? I tried changing the path to the .env file into an absolute one but that didn't help. I also experimented with positioning the dotenv.config before other imports as I found out this could be the reason but with no success.
Upvotes: 0
Views: 51
Reputation: 57
Imports are hoisted (see mozilla import Reference) This means that regardless of where you place your import statements, they will always be executed before any other code in the file.
And because you exported a direct connection code to the database in ./database/db.js
it runs before the .env
file is loaded.
To avoid this, you can wrap your database connection logic inside a function. This ensures that the connection does not start immediately after import.
Example ./database/db.js
:
import Sequelize from 'sequelize';
export function connect() {
const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD, {
host: process.env.DB_HOST,
dialect: 'mysql',
port: process.env.DB_PORT || 3306
});
return sequelize;
}
Example server.js
:
import dotenv from 'dotenv'
import express from 'express'
import cors from 'cors'
import sequelize from './database/db.js'
import {User} from './database/models.js'
dotenv.config({ path: '../.env' });
sequelize.connect()
Upvotes: -1