hobscrk777
hobscrk777

Reputation: 2647

How to access environment variables from Node app client

I have a Node app deployed to Elastic Beanstalk. I have javascript that runs client-side to make HTTP requests. The client-side javascript refers to routes that have the port hard-coded in the URI.

Elastic Beanstalk listens on port 8081. In my app.js file, I can write const port = process.env.PORT || 3000 and that works just fine (because this runs server-side).

The difficulty I'm having is in my client-side javascript. Suppose I have something like this

fetch('http://localhost:3000/users/login', {...})

To run on Elastic Beanstalk, I need to change this to 8081, but if I try to make it dynamic as in app.js, the process variable isn't found. Concretely, if I change the route to

const port = process.env.PORT || 3000 
fetch('http://localhost:' + port + '/users/login', {...})

then I get the following error: ReferenceError: Can't find variable: process.

I think I understand the crux of the problem (the environment variables are only available on the server), but I'm a Node/Express noob, and I'm not sure what the best way is to access the PORT environment variable on the client.

Upvotes: 1

Views: 3223

Answers (1)

varun agarwal
varun agarwal

Reputation: 1509

If you use webpack to bundle your FE application, you can configure your application to pass along the environment variables to the FE application.

This blog describes how it's done when using create react app. On inspecting the webpack config, two functions which essentially do the trick are:

function getClientEnvironment () {
  const raw = Object.keys(process.env)
    // Custom regex to allow only a certain category of variables available to the application
    .filter(<restrict the variables available to the application>)
    .reduce(
      (env, key) => {
        env[key] = process.env[key];
        return env;
      },
      {
        NODE_ENV: process.env.NODE_ENV || 'development'
      }
    );
  // Stringify all values so we can feed into Webpack DefinePlugin
  const stringified = {
    'process.env': Object.keys(raw).reduce((env, key) => {
      env[key] = JSON.stringify(raw[key]);
      return env;
    }, {}),
  };

  return { raw, stringified };
}

const env = getClientEnvironment()

And in your webpack configuration page, you could add these to the plugins section of webpack config:

new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
new webpack.DefinePlugin(env.stringified)

This will allow you to access the variables in js as

process.env.<VARIABLE NAME>

and in HTML as:

%<VARIABLE NAME>%

Upvotes: 2

Related Questions