Trying to use an environment variable from my dotenv file crashes my app because it seems the dotenv file is not loaded on time.
// server.js require('dotenv').config({ silent: process.env.NODE_ENV === 'production' }) console.log("Here is the env var: ", process.env.SPARKPOST_API_KEY) // works import express from 'express' import routes from './routes' (...) app.use('/api', routes); // routes/index.js import somecontroller from '../controllers/somecontroller' const routes = express.Router() routes.use('/somecontroller', somecontroller) // somecontroller.js import sendEmail from '../helpers/sparkpost' // ./helpers/sparkpost.js import SparkPost from 'sparkpost' var sparky = new SparkPost() // uses process.env.SPARKPOST_API_KEY export default function sendEmail() { }
crashes with error
Error: Client requires an API Key.
The API key is there, so it seems that sparkpost.js is instantiating new SparkPost()
before the dotenv
file gets loaded.
How do I work around this?
Advertisement
Answer
Javascript import
s are hoisted (but not Typescript!), so imported modules will initialize before any of the current modules initialization code gets to run. Fortunately imported modules are initialized in order, so a possible workaround is putting the config code in its own module:
// main.js <- make this your entry point import "./config"; import "./server"; // config.js import dotenv from "dotenv"; dotenv.config({ silent: process.env.NODE_ENV === 'production' }); // server.js import express from 'express'; import SparkPost from 'sparkpost'; const sparky = new SparkPost(); ...
Edit:
Even simpler:
// config.js import dotenv from "dotenv"; dotenv.config({ silent: process.env.NODE_ENV === 'production' }); // server.js <- make this your entry point import './config'; import express from 'express'; import SparkPost from 'sparkpost'; const sparky = new SparkPost(); ...
Edit:
The original question and answer was written with only Javascript in mind. Years have passed, and Typescript became popular. The Typescript compiler currently does not hoist imports, so you could just initialize dotenv
right in the entrypoint .ts
file, before the imports.