Skip to content

Best way to pass variables through Webpack? #386

Closed

Description

@louisscruz

Simple question, but I'm a little lost with the way webpack.DefinePlugin interacts with the application.

For my http calls, I'd like to have a variable that is dynamic based on the process.env.ENV. What's the best way to define a variable in both my webpack.config.js and webpack.prod.config.js files? And what's the best way to make them global variables in the application?

Activity

  1. rbao commented on Mar 5, 2016

    @rbao

    Not sure if this is the best way, but here is how I do it in both webpack.config.js and webpack.prod.config.js:

    new webpack.DefinePlugin({
      'process.env': {
        'ENV': JSON.stringify(metadata.ENV),
        'NODE_ENV': JSON.stringify(metadata.ENV),
        'HMR': HMR,
        'API_URL': JSON.stringify(process.env.API_URL)
      }
    })
    

    Then you can just use it in the code

    this._http.get(process.env.API_URL, options);
    

    For development I use dotenv to set the environment variable.
    For production just set environment variable as usual.

  2. louisscruz commented on Mar 6, 2016

    @louisscruz
    Author

    Perfect. Thanks!

  3. PatrickJS commented on Mar 7, 2016

    @PatrickJS
    Owner

    @rbao is correct. @rbao can you make a wiki page to talk briefly about this https://github.com/AngularClass/angular2-webpack-starter/wiki

  4. jshamley commented on Aug 4, 2016

    @jshamley

    Don't forget to restart Webpack after adding the environment variables or the system won't recognize them.

  5. marek1 commented on Sep 21, 2016

    @marek1

    I did all those things mentioned above, but

    when running npm start i get a process object that contains an EMPTY env object

  6. herr-bubu commented on Oct 28, 2016

    @herr-bubu

    I do it like this:

    new webpack.DefinePlugin({
         XMPP_HOST: JSON.stringify(process.env.XMPP_HOST || "http://localhost"),
        XMPP_PORT: JSON.stringify(process.env.XMPP_PORT || 5280)
    })
    

    and then in JS:

    export const XMPP_SERVER_URL = `${XMPP_HOST}:${XMPP_PORT}/http-bind`;
    
  7. Remco75 commented on Nov 20, 2016

    @Remco75

    @marek1 I noticed the same, there is a strange behaviour: When I de console.log(process) there is an empty env object .

    When I do console.log(process.env) it is filled with the proper stuff. I think it has to do with the string 'process.env' we set in the DefinePlugin

  8. nmccready commented on Nov 21, 2016

    @nmccready

    @Remco75

    @marek1 I noticed the same, there is a strange behaviour: When I de console.log(process) there is an empty env object .

    This strange behavior becomes clear when you look at the packed webpack file. Basically process does not get added to the global scope what so ever. Webpack does a search and replace for anything that is process.env and fills it in with that object specifically everywhere. So essentially it is a new instance of that config object every time. I think this was to not pollute the global space, but for minify purposes seems like a waste.

    Is there a option to make it part of the global namespace?

    Example:

    new webpack.DefinePlugin({
      '__PROCESS__': {
        'ENV': 'production',
      }
    })

    client code (source mapped):

    if(__PROCESS__.ENV === 'production'){
    //do something
    }

    Real Packed Code:

    client code (packed):

    if(({"ENV":"production"}).ENV === 'production'){
    //do something
    }

    It is not what you assumed it was

    window.__PROCESS__ = {"ENV":"production"};
  9. nmccready commented on Nov 21, 2016

    @nmccready

    Also this is talked about in some detail here webpack/webpack#868

    To get this working a little nicer for consuming your config objects I wrote this:

    function packinize(obj){
      _.each(obj, (v, i) => {
        if(_.isString(v))
          obj[i] = JSON.stringify(v)
        else if(_.isObject(v) && !_.isFunction(v))
          packinize(v)
      })
      return obj
    }
    
    const configPlugin = new webpack.DefinePlugin({
      __CONFIG__: packinize(frontendConfig)
    })
  10. jianghai commented on Nov 29, 2016

    @jianghai

    So, how could I do if __LANG__ is not defined by DefinePlugin ? Like this

    const module = __LANG__ ? require('./' + __LANG__) : require('./zh-cn')
  11. HendrikRoth commented on May 31, 2017

    @HendrikRoth

    Why not just this?

    new webpack.DefinePlugin({
      'process.env': process.env
    })
  12. al-the-x commented on Dec 9, 2017

    @al-the-x

    @HendrikRoth please don't ever do this, as you've just exposed the environment of the process that you built with to your bundle... And subsequently the internet. Many sensitive values are potentially contained therein, unless DefinePlugin is sanitizing them somehow... Although I can't imagine how.

  13. gezichenshan commented on Feb 11, 2018

    @gezichenshan

    @al-the-x so it means the webpack.DefinePlugin rewrites the process.env as a global variable in a webpack project?

    new webpack.DefinePlugin({
      'process.env': require('../config/dev.env')
    })
    

    ../config/dev.env:

    module.exports = {
      NODE_ENV: process.env.NODE_ENV,
      BASE_URL : process.env.BASE_URL,
      MULTILOAN: process.env.MULTILOAN
    }
    

    so can we change the process.env in 'process.env': require('../config/dev.env') to another name like 'globalEnv'

  14. al-the-x commented on Mar 2, 2018

    @al-the-x

    In the example from above to which I objected, consider code like this:

    // some/project/file.js
    if (process.env.NODE_ENV === 'production') {
      doSomethingForProduction();
    }

    The plugin new webpack.DefinePlugin({ 'process.env.NODE_ENV': process.env.NODE_ENV }) will result in code like this when process.env.NODE_ENV is the string 'production':

    // some/project/file.js
    if ('production' === 'production') {
      doSomethingForProduction();
    }

    The config new webpack.DefinePlugin({ 'process.env': process.env }), while simpler, will instruct webpack to replace process.env with an object matching the value provided, so that subsequent keys can be retrieved, e.g.

    // some/project/file.js
    if (({ /* all of process.env as key: value */ }.NODE_ENV === 'production') {
      doSomethingForProduction();
    }

    The suggestion you made @gezichenshan, would be much safer, but why not just put those definitions in the DefinePlugin config instead of an external file? If there were lots of values that you needed to pick out of process.env, then maybe a module that did just that would make sense:

    const _ = require('lodash');
    
    const KEYS = [
      'NODE_ENV',
      'BASE_URL',
      'SOMETHING_ELSE',
      // . . . so many others
    ];
    
    module.exports = _.chain(KEYS)
      .map(key => `process.env.${key}`)
      .map(path => [ path, _.get(process.env, path) ])
      .fromPairs()
    .value();

    But likely that's not practical, either, since that would require a large number of environment variables passed to the startup script. At that point, another external configuration file would be better. Probably one that switches values dependent on... process.env.NODE_ENV...!

  15. skwid138 commented on Jul 6, 2018

    @skwid138

    JSON not JS

    I probably should've caught this right away, but I wasn't wrapping the values in JSON.strinify() and was throwing console errors that listed the key, but said it wasn't defined. Which makes sense, but took me a few minutes to figure out why. Hope this helps others in the future.

    Originally I was using the below
    new webpack.DefinePlugin({ 'process.env': { 'WP_ENV': process.env.WP_ENV, 'WP_DEBUG': process.env.WP_DEBUG, } }),

    Then updated it to this to make it work properly
    new webpack.DefinePlugin({ 'process.env': { 'WP_ENV': JSON.stringify(process.env.WP_ENV), 'WP_DEBUG': JSON.stringify(process.env.WP_DEBUG), } }),

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions