Skip to content
Advertisement

ES6 import happening before .env import

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 imports 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.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement