skwidbreth
skwidbreth

Reputation: 8404

Webpack/Express - environment variables not found by server

In my Express/React app, I am using Webpack to handle server-side rendering. However, I am experiencing a build error related to environment variables that I'm trying to access in my Express server script.

In the server script, index.js, I am setting a few variables like so:

const gitCommit = process.env.GIT_COMMIT || require("./gitignore/git_commit.js"),
    buildDate = process.env.BUILD_DATE || require("./gitignore/build_date.js")

And since I am running a test production build on my local machine, I delete the gitignore/ directory and set those environment variables:

$ export GIT_COMMIT="test commit hash"
$ export BUILD_DATE="test build date"

Then I npm run build, which executes the following scripts:

"build:client": "webpack --config webpack.config.js",
"build:server": "webpack --config webpack.server.config.js",
"build": "npm run build:client && npm run build:server"

build:client executes with no problem, but build:server throws errors...

ERROR in ./index.js
Module not found: Error: Can't resolve './gitignore/git_commit.js' in '/Users/filepath'
 @ ./index.js 12:38-74

ERROR in ./index.js
Module not found: Error: Can't resolve './gitignore/build_date.js' in '/Users/filepath'
 @ ./index.js 13:42-78

implying that the two environment variables referenced in index.js can't be found, and so it's looking for the gitignore/ instead, which shouldn't exist (I mean, it does exist locally, but I've deleted since I'm simulating a production build).

Here is the complete webpack.server.config.js:

const fs = require("fs"),
    path = require("path")// ,
    // ExtractTextPlugin = require("extract-text-webpack-plugin")

module.exports = {
    "entry": path.resolve(__dirname, "index.js"),
    // keep node_module paths out of the bundle
    "externals": fs.readdirSync(path.resolve(__dirname, "node_modules")).concat(["react-dom/server", "react/addons"]).reduce((ext, mod) => {
        ext[mod] = `commonjs ${mod}`
        return ext
    }, {}),
    "module": {
        "loaders": [
            {
                "exclude": /node_modules/,
                "loader": "babel-loader",
                "query": { "presets": ["react", "es2015", "stage-2"] },
                "test": /\.jsx$/
            },
            {
                "exclude": /node_modules/,
                "loader": "babel-loader",
                "query": { "presets": ["react", "es2015", "stage-2"] },
                "test": /\.js$/
            }
        ]
    },
    "node": {
        "__dirname": true,
        "__filename": true
    },
    "output": {
        "filename": "server.bundle.js"
    },
    "target": "node"
}

Now I expect that gitignore/ would not be found, but what I don't understand is why the two environment variables that I set are not being detected by index.js - they are definitely set in the console before I even run the build command. If I console.log() them in the beginning of webpack.server.config.js, it logs them correctly, and if I run my development version instead (which doesn't use the server config), I can log them correctly in index.js. What gives?

Node version 6.11.1, NPM version 3.10.10, Webpack version 2.6.0.

Upvotes: 1

Views: 1360

Answers (1)

Amberlamps
Amberlamps

Reputation: 40448

Your environment variables are only available when Webpack runs, but not when you execute your index.js. You will need to use the EnvironmentPlugin in your Webpack config like that:

plugins: [new webpack.EnvironmentPlugin(['GIT_COMMIT ', 'BUILD_DATE'])]

That plugin will replace the variables by their actual values.

HINT: Do not use ||. Webpack does not know how to optimize it. Try the ternary operator:

const gitCommit = (process.env.GIT_COMMIT) ? (
  process.env.GIT_COMMIT
) : (
  require('./gitignore/git_commit.js')
);

Webpack will bundle this to:

const gitCommit = (true) ? (
  "test commit hash"
) : (
  require('./gitignore/git_commit.js')
);

No IgnorePlugin is needed. Even better, with the UglifyJSPlugin, your code will be optimized to const gitCommit = "test commit hash";. In some cases gitCommit is removed completely as a variable. Its string value will be used instead anywhere where you applied gitCommit.

Upvotes: 3

Related Questions