Why does production build of React app (with Webpack and Babel) use wrong development env with HMR, which causes errors?
Asked Answered
E

4

16

I'm trying to create a production build of my React project, but it picks the wrong configuration.

In the development version I'm using HMR (Hot Module Replacement). This is configured in .babelrc, under env > development > plugins. When adding an extra node env > production it seems to be ignored. It's still using the development configuration with HMR, which causes an error:

Uncaught Error: locals[0] does not appear to be a module object with Hot Module replacement API enabled. You should disable react-transform-hmr in production by using env section in Babel configuration. See the example in README: https://github.com/gaearon/react-transform-hmr

Of course I've checked that information, but everything seems right. When I removed the HMR plugin from .babelrc's development config, it works, proving it is indeed using the development config instead of production. Here's my files:

package.json

{
  "name": "myproject",
  "main": "index.js",
  "scripts": {
    "serve": "cross-env NODE_ENV=development webpack-dev-server --content-base bin/ --devtool eval --progress --colors --hot --inline",
    "deploy": "cross-env NODE_ENV=production BABEL_ENV=production webpack -p --config webpack.production.config.js"
  }
  //dependencies omitted in this example
}

.babelrc

{
    "presets": ["react", "es2015", "stage-0"],
    "plugins": [
        ["transform-decorators-legacy"]
    ],
    "env": {
        "development": {
            "plugins": [
                ["react-transform", {
                    "transforms": [{
                        "transform": "react-transform-hmr",
                        "imports": ["react"],
                        "locals": ["module"]
                    }]
                }]
            ]
        },
        "production": {
            "plugins": []
        }
    }
}

As you can see in package.json > scripts > deploy, I'm even explicitly setting the BABEL_ENV to 'production'.

Why is this happening? How do I make sure the production build ignores the HMR plugins?

By the way, searching often leads to issue #5 on the React-transform-HMR Github page, which is a long thread without a clear solution.

Edit 2016.03.30: Adding the Babel part of my webpack config on request. Edit 2016.04.06: Adding whole webpack file on request.

webpack.production.config.js

require('es6-promise').polyfill();
var path = require('path');

module.exports = {
    entry: './main.jsx',
    context: __dirname + path.sep + 'src',
    output: {
        path: path.resolve(__dirname, './bin'),
        filename: 'index.js'
    },
    devServer: {
        port: 3333
    },
    module: {
        loaders: [
            {
                test: /\.js(x?)$/,
                exclude: /node_modules/,
                loader: 'babel',
                query: {
                    presets: ['react', 'es2015', 'stage-0'],
                    plugins: [['transform-decorators-legacy']]
                }
            },
            {
                test: /\.css$/,
                loader: "style!css"
            },
            {
                test: /\.scss$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'style-loader!css-loader!sass-loader?sourceMap'
            }
        ]
    }
};
Ensheathe answered 22/3, 2016 at 11:50 Comment(6)
What OS do you run ?Stumpy
I'm on OSX but my team mate is on Windows. I'll modify the script lines, as we are using cross-env now.Ensheathe
Could you show the webpack config just to be sure ?Stumpy
Done, just the Babel loader module part I suppose?Ensheathe
Have you tried setting BABEL_ENV within your webpack.config.js file? I use the react-hmre preset and that is how I'm setting it to production or development.Portland
For me it looks fine and a similar set up works for me so there must be some external issue here :(Stumpy
R
8

The only thing that worked for me, is that I wrote -

process.env.NODE_ENV = 'production';

at the beginning of my webpack.config.prod.js file.

Ruder answered 13/7, 2016 at 10:42 Comment(0)
T
5

It seems that no matter what Babel keeps using the development section of the env value specified in .babelrc. What solved the problem for me, was to use name other than 'development' and set that as the value of BABEL_ENV.

"env": {
    "dev": {
        "plugins": [
        ]
    },
    "production": {
    }
}

I use separate conf for development. In plugins I have:

new webpack.DefinePlugin({
  'process.env': {
    'NODE_ENV': JSON.stringify('development'),
    'BABEL_ENV': JSON.stringify('dev')
  }
}),
Towandatoward answered 24/5, 2016 at 14:53 Comment(0)
S
0

& in shell means that it will run in the background, so maybe your variable declaration is not caught by the build stuff that happens at the same time. The good thing is that you can just prepend the command with the variable declarations.

You could simplify the commands like this:

"serve": "NODE_ENV=development webpack-dev-server --content-base bin/ --devtool eval --progress --colors --hot --inline",
"deploy": "NODE_ENV=production BABEL_ENV=production webpack -p --config webpack.production.config.js"
Stumpy answered 30/3, 2016 at 11:53 Comment(1)
Thanks @Mijamo. We had already removed SET and the &-signs and added cross-env for windows-compatibility. (I've modified the question to reflect this) However, the problem persists, so the & was not causing the problem...Ensheathe
S
0

You can just use the babel-preset-react-hmre.

.babelrc

{
    "presets": ["react", "es2015", "stage-0"],
    "plugins": [
        "transform-decorators-legacy"
    ],
    "env": {
        "development": {
            "presets": ["react-hmre"]
        }
    }
}

webpack

    {
        test: /\.js(x?)$/,
        exclude: /node_modules/,
        loader: 'babel',
        query: {
            presets: ['es2015', 'react', 'stage-0'],
            plugins: ['transform-decorators-legacy'],
            env: {
              development: {
                presets: ['react-hmre']
              }
            }
        }
    }
Schrader answered 4/4, 2016 at 13:41 Comment(7)
Though that seems to stop that error, Babel is still using the env.development part of my configuration and ignoring my env.production. So I'm not getting a successfully built js-file. Any ideas on that?Ensheathe
@Ensheathe i need to see your complete webpack file. Or better the repo if possibleSchrader
Ok, I modified the question with the full webpack config file.Ensheathe
ok I have made a quick Gist of what kind of setup i use. When I get a chance will make a working repo to see if it works.Schrader
@Ensheathe Any news? I'm facing a similar problem, setting NODE_ENV everywhere, can't think of anything else to try.... Could you please post your solution here? Thanks.Ruder
Hi @alexunder, yes, in the end there was no way to get the compiler to respect the .babelrc config. So I stopped using that file and made two webpack.configs. One for debug, one for production. The babel configuration is set in the webpack files, eliminating the whole problem. Let me know if that works for you. I'll add this answer soon.Ensheathe
@Ensheathe Hi, yep, you can see my answer below, did the same thing eventually :)Ruder

© 2022 - 2024 — McMap. All rights reserved.