Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack: process.env undefined using DefinePlugin and DotEnv

I would like to get my variable from my .env file but I always get undefined

This is my js code :

require('dotenv').config();
class Header extends React.Component{
    constructor(props){...}
    render(){
        console.log("NODE ENV", process.env.NODE_ENV);
        console.log("REACT_APP_MYAPP", process.env.REACT_APP_MYAPP);
        ...
   }
}

This prints :

NODE_ENV development

REACT_APP_MYAPP undefined

In my package.json there is :

"scripts":{
      "start" : "webpack-dev-server --config webpack.dev.js",
      "build" : "webpack --config webpack.prod.js"
 }

And in my webpack.dev.js:

const webpack = require("webpack");
const merge = require("webpack-merge");
const path = require("path");
const common = require("./webpack.common.js");

module.exports = merge.smart(common, {
    devServer: {
        contentBase: path.resolve(__dirname, "dist"),
        hot: true,
        overlay: {
            warnings: true,
            errors: true
        },
        inline :true,
        historyApiFallback: true,
        port: 8085
    },
    devtool: "inline-sourcemap",
    optimization: {
        namedModules: true
    },
    plugins: [
        new webpack.HotModulReplacementPlugin(),
        new webpack.DefinePlugin({
            "process.env.NODE_ENV": JSON.stringify("development"),
            "process.env.REACT_APP_MYAPP": JSON.stringify(process.env.REACT_APP_MYAPP)
        })
    ],
    mode: "development"
});

And I placed my .env file at the root of my project, next to webpack.dev.js and package.json:

REACT_APP_MYAPP=http://localhost:8080/

So I think, it doesn't success to get the variable in the file.

How can I get the REACT_APP_MYAPP value in the code please ?

like image 788
anais1477 Avatar asked Mar 15 '19 15:03

anais1477


People also ask

What is DefinePlugin in Webpack?

The DefinePlugin replaces variables in your code with other values or expressions at compile time. This can be useful for allowing different behavior between development builds and production builds.

What is Node_env used for?

NODE_ENV is an environment variable that stands for node environment in express server. The NODE_ENV environment variable specifies the environment in which an application is running (usually, development or production).


Video Answer


3 Answers

Journeying through the deep, dark rabbit hole will lead you to the following facts:

  • Webpack 5 no longer provides process or other Node.js variables.
  • The role of DefinePlugin requires redefining.
  • Values passed to DefinePlugin must be stringified, even if they're strings.
  • EnvironmentPlugin makes things more confusing, given Webpack 5.
  • process.env isn't really something you should be using in the frontend.
  • You can use polyfills to re-add process and others back in, but there is a reason it's no longer available.
  • dotenv-wepack is neither necessary nor the way to go.
  • The reason for using process.env is to access variables globally. But it's a passenger on the wrong flight. We can drop it and instead just access the intended variable directly:
plugins: [
    new DefinePlugin({
        // With dotenv (values must be stringified)
        ...Object.entries(dotenv.config().parsed).reduce((acc, curr) => ({...acc, [`${curr[0]}`]: JSON.stringify(curr[1]) }), {}),
        
        // Without dotenv 
        'myString': JSON.stringify('IAmAString')
    })
  ]

In the frontend:

declare var myString: string;
console.log(myString); // 'IAmAString'

If you have several objects with variables it makes sense to abstract the stringification:

// Create a function to stringify values
function stringifyValues(object: {[key: string]: any;}){
    return Object.entries(object).reduce((acc, curr) => ({...acc, [`${curr[0]}`]: JSON.stringify(curr[1]) }), {} as { [key: string]: string; });
}

// use with DefinePlugin
plugins: [
    new DefinePlugin({
      ...stringifyValues(dotenv.config().parsed),
      ...stringifyValues(dotenv.config({ path: '/.env.special' }).parsed),
      'myObject': stringifyValues({ 
            name: 'Object', 
            description: 'to be an object' 
      })
    })
  ]

If you really want access to process.env:

plugins: [
    new DefinePlugin({
        // this might expose confidential data about your environment
        'process.env': JSON.stringify(process.env),

        // the correct way
        'process.env.USERNAME': JSON.stringify('Donald Hump')
    })
  ]

In the frontend:

declare var process: any;
console.log(process) // will NOT work, because process hasn't been injected
console.log(process.env); // will work but risky
console.log(process.env.USERNAME); // correct: 'Donald Hump'
like image 199
Jai Avatar answered Oct 20 '22 15:10

Jai


First solution by adding REACT_APP_MYAPP in start didn't worked. But second solution worked.

SOLUTION:

Adding require('dotenv').config() file inside my webpack.dev.js and replacing :

   new webpack.DefinePlugin({
        "process.env.NODE_ENV": JSON.stringify("development"),
        "process.env.REACT_APP_MYAPP": JSON.stringify(process.env.REACT_APP_MYAPP)
    })

with

    new webpack.EnvironmentPlugin(['NODE_ENV', 'REACT_APP_MYAPP']);

Thank you!

like image 37
anais1477 Avatar answered Oct 20 '22 15:10

anais1477


There's a few ways you could make this work.

The easiest to test is to change your "start" : "webpack-dev-server --config webpack.dev.js", to "start" : "REACT_APP_MYAPP=http://localhost:8080/ node webpack-dev-server --config webpack.dev.js",

This will inject the environment variable and it will be available during the webpack build process. You can use this technique whenever using npm or node to run a command. For instance, NODE_ENV='development REACT_MY_APP=http://localhost:8080/ node myapp.js and both will be available on process.env.

You could also call your require('dotenv').config() file inside your webpack.dev.js. Then it would be set during your usage of the DefinePlugin.

Generally, you don't use the npm start command to run your development server.

As the application grows you should look at the Webpack Environment Plugin. Then you can use the .env for the "production" build settings, requiring it in the production webpack.prod.js, while setting your default/fallback environment variables using the plugin.

like image 1
adamrights Avatar answered Oct 20 '22 14:10

adamrights