Search code examples
javascriptnode.jswebpackwebpack-4

Webpack: How to inject process.env runtime on client(browser) side making build independent of environment


SHORT Question

I'm looking some way to tell Webpack that, do not do anything with process variable, just treat as like any other global variable (so it refers to window.process in client bundle). If not possible, then a way to inject variables in process.env of Webpack during runtime on client.

LONG Explaination

At the moment, I use Webpack to pack my React (SSR) application. I have 5 environments like dev1, dev2... staging and production. I want to re-use the same build and keep things configurable like say Google Analytics ID on each environment is different.

Backend Dot ENV module does the job. I can define all constants as KEY=value pair in .env file and load them run time and use as process.env.KEY in the code.

I was trying to replicate same behaviour for the front end side (or shared files). Say I have a baseService.js which makes call to fetch. It can be used from node + client as well. It uses variables like process.env.HOST. Until now I was creating separate build for each environment, therefore had this defined in Webpack using webpack.DefinePlugin plugin to be able to use this on client side bundle.

Now as I want to re-use the builds, I capture all constants in process.env see if any of them is usable on client side by matching them with PUBLIC_(.*) (It would match PUBLIC_KEY), if yes pack then in array and add in main html file as object as shown below:-

window.process = {ENV: { PUBLIC_GA_ID: '1235', PUBLIC_FOO: 'bar' }}

When I bundle my client using webpack and execute process.env.PUBLIC_GA_ID is undefined (although it is there in head html as global window.process variable). It is because webpack still injecting process variable from Node to the front end which has env object as blank {} object. I had it debugged below is the screenshot.

enter image description here

Above is console log of process variable in a baseService.js file. Obviously I cannot use window.process here because then it would fail when file is being used in Node.js

I'm looking some way to tell Webpack that, do not do anything with process variable, just treat as like any other global variable (so it refers to window.process in client bundle). If not possible, then a way to inject variables in process.env of Webpack during runtime on client.


Solution

  • I think instead playing with Webpack to do this job, I have settled with for the simplest solution. If anyone has any better answer, please do post.

    I created a utility function as follows:-

    export const getEnv = key => {
      if (typeof window === 'undefined') {
        // node
        return process.env[key]
      }
      // browser
      return window.process.env[key]
    }
    

    Now I call getEnv('PUBLIC_KEY') or getEnv('NODE_ENV') both in node and in browser and works perfectly fine.

    Although I'd still prefer the better way Webpack supports option to take process.env run time or inject API for browser