Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't access process.env values using dynamic keys

I have a nextjs (not sure if it has any relevance or does it apply to nodejs as a whole) project in which I would like to access a value from process.env using a dynamic key:

const myKey = 'MY_KEY'
console.log(process.env[myKey]) //undefined

For reference, I have tried:

console.log(process.env['MY_KEY']) // gives value under MY_KEY
console.log(process.env.MY_KEY) // works too
like image 597
Jacobdo Avatar asked Oct 01 '20 09:10

Jacobdo


1 Answers

First of all, one thing to note, that if you want to use env variables on the client then you need to prefix them with NEXT_PUBLIC_, or use older way of exposing them to the client inside next.config.js.

As for the question, this is due to nature of how Webpack DefinePlugin works which I believe NextJs uses internally. It does direct text replacement at build time, in simpler words it just looks for process.env.MY_KEY string and replaces it with value. But if you destructure it then plugin just can't find process.env.MY_KEY string anymore and you are getting nothing (process.env object is generated anyway, but it will be empty).

Although this only true for client side code, because for server side Next actually uses real process.env object and destructuring will work there.

For example, if we have NEXT_PUBLIC_MY_KEY=somevalue and we log this somewhere in the code:

  const key = 'NEXT_PUBLIC_MY_KEY';

  console.log(process.env.NEXT_PUBLIC_MY_KEY);
  console.log(process.env['NEXT_PUBLIC_MY_KEY']);
  console.log(process.env[key]);
  console.log(process.env);

On client side you will get:

somevalue
somevalue
undefined
{} // empty object

And on server side you will get:

somevalue
somevalue
somevalue
{ ... } // object with all available env values, even system ones

There is a little bit of info about it in older env docs.

Workaround

You could probably use Runtime Configuration, but it has it's own limitations, for example, I think the page should be dynamic (should use getInitialProps or getServerSideProps) to work.

// next.config.js
module.exports = {
  publicRuntimeConfig: {
    myEnv: 'somevalue',
    // or actually use process.env variables, they are all available here
    myEnv2: process.env.MY_ENV
  },
};

import getConfig from 'next/config';

const key = 'myEnv';

getConfig().publicRuntimeConfig[key] // 'somevalue' 

Or just pass your variables through getServerSideProps like the other answer mentioned.

EDIT: I've actually just tested publicRuntimeConfig and it works even on static pages, at least if you are using next start. Not sure why docs says that the page should have getServerSideProps. So this might be the solution in the end.

like image 162
Danila Avatar answered Nov 02 '22 01:11

Danila