skwidbreth
skwidbreth

Reputation: 8404

Webpack - unable to set global variables unless set as 'process.env'

I'm running a React app with Webpack version 3.6.0, and I'm having trouble using the DefinePlugin to set global variables - values that are set 'normally', as per the documentation are not available throughout the app... however, if I wrap values in an object named process.env, the variables are available throughout the app, albeit with the prefix process.env.

For example, here is what I'd like my DefinePlugin to look like:

plugins: [
    new Webpack.DefinePlugin({
        "NODE_ENV": process.env.NODE_ENV ? JSON.stringify(process.env.NODE_ENV) : JSON.stringify("development"),
        "SIGNUP_PATH": JSON.stringify("signup")
    })
]

This does not work - trying to console.log(NODE_ENV) or console.log(SIGNUP_PATH) does nothing, the variables are undefined.

Surprisingly (or maybe not, maybe there's just something I don't know), this works:

plugins: [
    new Webpack.DefinePlugin({
        "process.env": {
            "NODE_ENV": process.env.NODE_ENV ? JSON.stringify(process.env.NODE_ENV) : JSON.stringify("development"),
            "SIGNUP_PATH": JSON.stringify("signup")
        }
    })
]

and I can access the variables with console.log(process.env.NODE_ENV) and console.log(process.env.SIGNUP_PATH), etc.

Why is it that I have to put everything into an object called process.env in order to access it as I would a global? Am I doing something wrong here, or is there just something that I don't understand about this?

Upvotes: 0

Views: 1042

Answers (3)

skwidbreth
skwidbreth

Reputation: 8404

Ultimately, this problem was due to the fact that I built my app to make use of server-side rendering - it needs two separate Webpack configs, but initially I was only including the DefinePlugin settings on the client. Basically, I put everything for the DefinePlugin into a separate file, imported it into both the client and server configs, and then bundled it into a final webpack.config.prod.js for production (or a similar webpack.config.dev.js for development... only production shown below). Here's how it all came together:

webpack_config.define-plugin-config.js:

module.exports = {
    "API_URL": process.env.API_URL ? JSON.stringify(process.env.API_URL) : JSON.stringify("http://localhost:4000/api/v1/"),
    "SOME_OTHER_VAR": JSON.stringify("foo")
}

webpack.config.server.js:

const Webpack = require("webpack"),
    path = require("path"),
    definePluginConfig = require("./webpack_config/define-plugin-config"),
    rule_js = require("./webpack_config/rule"),
    resolve = require("./webpack_config/resolve")

module.exports = {
    "entry": {
        "component": path.join(__dirname, "js/containers/index.jsx")
    },
    "output": {
        "path": path.join(__dirname, "../priv/static/server/js"),
        "filename": "app.js",
        "library": "dl",
        "libraryTarget": "commonjs2"
    },
    "module": {
        "rules": [
            rule_js
        ]
    },
    "resolve": resolve,
    "plugins": [
        new Webpack.DefinePlugin(definePluginConfig)
    ]
}

webpack.config.client.js:

const Webpack = require("webpack"),
    ExtractTextPlugin = require("extract-text-webpack-plugin"),
    CopyPlugin = require("copy-webpack-plugin"),
    path = require("path"),
    definePluginConfig = require("./webpack_config/define-plugin-config"),
    rule_js = require("./webpack_config/rule"),
    resolve = require("./webpack_config/resolve")

module.exports = {
    "entry": [
        path.join(__dirname, "js/index.jsx"),
        path.join(__dirname, "styles/index.scss")
    ],
    "output": {
        "path": path.join(__dirname, "../priv/static"),
        "filename": "js/app.js",
        "publicPath": "/"
    },
    "module": {
        "rules": [
            rule_js,
            {
                "test": /\.scss$/,
                "use": ExtractTextPlugin.extract({
                    "fallback": "style-loader",
                    "use": ["css-loader", "sass-loader"]
                })
            },
            {
                "test": /\.css$/,
                "use": ExtractTextPlugin.extract({
                    "fallback": "style-loader",
                    "use": ["css-loader?modules&importLoaders=1&localIdentName=[local]"]
                })
            }
        ]
    },
    "resolve": resolve,
    "plugins": [
        new Webpack.DefinePlugin(definePluginConfig),
        new ExtractTextPlugin({
            "filename": "css/app.css",
            "allChunks": true
        }),
        new CopyPlugin([{ "from": path.join(__dirname, "static") }])
    ]
}

webpack.config.prod.js:

const clientWebPackConfig = require("./webpack.config.client"),
    serverWebPackConfig = require("./webpack.config.server"),
    UglifyJsPlugin = require("uglifyjs-webpack-plugin"),
    webpackConfig = [clientWebPackConfig, serverWebPackConfig],
    uglifyJsPluginOptions = { "sourceMap": true }

webpackConfig[0].plugins = [...webpackConfig[0].plugins, new UglifyJsPlugin(uglifyJsPluginOptions)]

module.exports = webpackConfig

Upvotes: 0

Gavin Thomas
Gavin Thomas

Reputation: 1867

Here is a working example. Anywhere In my code I can reference __ API_URL __

require('dotenv').config({ path: `${__dirname}/src/.dev.env` });
const production = process.env.NODE_ENV === 'production';

const { DefinePlugin, EnvironmentPlugin } = require('webpack');
const HtmlPlugin = require('html-webpack-plugin');
const CleanPlugin = require('clean-webpack-plugin');
const UglifyPlugin = require('uglifyjs-webpack-plugin');
const ExtractPlugin = require('extract-text-webpack-plugin');

let plugins = [
  new EnvironmentPlugin(['NODE_ENV']),
  new ExtractPlugin('bundle-[hash].css'),
  new HtmlPlugin({ template: `${__dirname}/src/index.html` }),
  new DefinePlugin({
    __DEBUG__: JSON.stringify(!production),
    __API_URL__: JSON.stringify(process.env.API_URL),
    __GOOGLE_CLIENT_ID__: JSON.stringify(process.env.GOOGLE_CLIENT_ID),
    __AWS_ACCESS_KEY_ID__: JSON.stringify(process.env.AWS_ACCESS_KEY_ID),
    __AWS_SECRET_ACCESS_KEY__: JSON.stringify(process.env.AWS_SECRET_ACCESS_KEY),
  }),
];

Upvotes: 1

Stephanie Dover
Stephanie Dover

Reputation: 97

leave out the quotes. "NODE_ENV" should be NODE_ENV

Upvotes: 0

Related Questions