cphill
cphill

Reputation: 5914

NextJS with ExpressJS Server ENV Variables Not Loading Before Use

I have a NextJS application with an ExpressJS server to handle certain parts of the application for authentication reasons. The application runs without problems until I try to use env variables for my database configuration using the Sequelize ORM. At first I thought that maybe it is due to nuances occurring due to NextJS and ExpressJS running together, but after console logging at different points in the code, it looks like my Sequelize DB config file is running and setting the env variables before NextJS/ExpressJS loads them from the file.

Can anyone provide context on why that might be?

config/sequelize.js my DB config file:

console.log("Loading config file")
console.log(process.env.DB_DATABASE) // Returns undefined

module.exports = {
  "development": {
    "username": "username",
    "password": "password",
    "database": process.env.DB_DATABASE, // undefined
    "dialect": "postgres"
  },
}

server.js My NextJS & ExpressJS server:

console.log('server.js - file read')
console.log('process.env.DB_DATABASE: ' + process.env.DB_DATABASE) // Returns undefined

const express = require('express')
const next = require('next')

const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
    
app.prepare()
.then(() => {
    const server = express()

    console.log('app.prepare() triggered. Express server configuration started below')
    console.log('process.env.DB_DATABASE: ' + process.env.DB_DATABASE) // Returns "db_template". CORRECT!

    //  Setting proxy for session handlng that is required for non-dev servers
    if (!dev){
        server.set('trust poxy', 1)
    }

    //  ExpressJS Routes
    server.use(routes);

    //  Mount the router on the app 
    //  Any routes that aren't handled by ExpressJS are handled by NextJS
    server.get('*', (req, res) => {
        return handle(req, res)
    })

    server.listen(3000, (err) => {
        if (err) throw err
        console.log('> Ready on http://localhost:3000')
        console.log('Expressjs server listening')
        console.log('process.env.DB_DATABASE: ' + process.env.DB_DATABASE) // Returns "db_template". CORRECT!
    })
})
.catch((ex) => {
    console.error(ex.stack)
    process.exit(1)
})

Here is the terminal output in order of execution:

npm run dev

> [email protected] dev /Users/user/dev/nextjs/auth-boilerplate
> nodemon server.js

[nodemon] 2.0.7
[nodemon] reading config ./nodemon.json
[nodemon] to restart at any time, enter `rs`
[nodemon] or send SIGHUP to 81315 to restart
[nodemon] ignoring: ./node_modules/**/* ./.next/**/*
[nodemon] watching path(s): controllers/**/* models/**/* config/**/* libs/**/* ssr-server.js
[nodemon] watching extensions: js,json
[nodemon] starting `node server.js`
[nodemon] forking
[nodemon] child pid: 81317
[nodemon] watching 9 files

server.js - file read
process.env.DB_DATABASE: undefined

Loading config
undefined

Browserslist: caniuse-lite is outdated. Please run:
npx browserslist@latest --update-db
Loaded env from /Users/connorphillips/dev/nextjs/auth-boilerplate/.env
info  - Using external babel configuration from /Users/connorphillips/dev/nextjs/auth-boilerplate/.babelrc
event - compiled successfully

app.prepare() triggered. Express server configuration started below
process.env.DB_DATABASE: email_local


> Ready on http://localhost:3000
Expressjs server listening
process.env.DB_DATABASE: email_local

Summary of execution order:

  • server.js file is read
  • config/sequelize.js file is read
  • env loaded from .env.development
  • server.js app.prepare() is triggered
  • server.js server.listen() is triggered

Upvotes: 0

Views: 894

Answers (1)

ES Hyun
ES Hyun

Reputation: 26

I encountered the same issue.

Imported modules at top of code are initialized before app.prepare() is executed.
I think your config/sequelize.js is imported from "routes" module.

my workaround is putting "routes" import in app.prepare().then().

app.prepare()
.then(() => {
    ...

    // ExpressJS Routes
    // use require because javascirpt import is hoisted.
    server.use(require('./your-routes-path')); // if you use module.exports
    server.use(require('./your-routes-path').default); // if you use export default

    ...
})

Upvotes: 1

Related Questions