React: Webpack fails to build React with SyntaxError

Created on 2 Dec 2016  ·  6Comments  ·  Source: facebook/react

I've found a strange issue with React when packaged using webpack. The issue doesn't make sense, as both the browser (when used in development mode) and the webpack build pipeline throw SyntaxError on ternary operator's :. Not sure who to blame: webpack, auth0-lock or React, but everything fails inside of React, so here we go.

Setup

Here is my setup:
https://github.com/Remper/react_bug

It's an empty Angular2 application that shows auth0-lock.

Auth0-lock uses React as a dependency and everything is being bundled by webpack (the exact config is in the repository as well).

What is the current behavior?

Now when I try to launch this setup I get a SyntaxError which points to a perfectly valid line in React sources. In particular, it doesn't like ternary operators much: if I replace them with ifs manually — it breaks somewhere else inside of React:

ERROR in js/app.6a0a1796a34dcc432afe.js from UglifyJs
SyntaxError: Unexpected token: punc (:) [./~/react/lib/ReactComponentTreeHook.js:164,0][js/app.6a0a1796a34dcc432afe.js:13802,8]

This is how it looks when I disable UglifyJs: http://remper.ru/bug/

What is the expected behavior?

React should work when included as a dependency and packaged with webpack.

npm run build shouldn't report any issues.

Most helpful comment

@Remper alright, I cloned down the project and I think I figured out the problem. It's not an issue with your ternary operator, it's an issue with how process.env.NODE_ENV is being replaced by DefinePlugin.

I removed NoErrorsPlugin from the config so the assets would still be emitted, and then ran it in the browser. The offending line is:

  {"ENV":"build"}.NODE_ENV !== 'production' ? warning(element, 'ReactComponentTreeHook: Missing React element for debugID %s when ' + 'building stack', id) : void 0;

The issue is with:

{"ENV":"build"}.NODE_ENV

Which is coming from:

        new webpack.DefinePlugin({
            // Environment helpers
            'process.env': {
                ENV: JSON.stringify(ENV)
            }
        }),

The problem here is that you're not replacing process.env.NODE_ENV, you're just replacing process.env with an object that has an ENV property. You can't do property access on an object literal definition, so it throws.

You can fix this by properly replacing instances of process.env.NODE_ENV by changing ENV to NODE_ENV

      new webpack.DefinePlugin({
            // Environment helpers
            'process.env': {
                NODE_ENV: JSON.stringify(ENV)
            }
        }),

I tested this locally and it built successfully 👍

All 6 comments

What is the exact line at js/app.6a0a1796a34dcc432afe.js:13802,8?

@gaearon

Looks like this in app.js:

"use strict";
eval("/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar _assign = __webpack_require__(10);\n\nvar ReactChildren = __webpack_require__(693);\nvar ReactComponent = __webpack_require__(242);\nvar ReactPureComponent = __webpack_require__(697);\nvar ReactClass = __webpack_require__(694);\nvar ReactDOMFactories = __webpack_require__(695);\nvar ReactElement = __webpack_require__(71);\nvar ReactPropTypes = __webpack_require__(696);\nvar ReactVersion = __webpack_require__(701);\n\nvar onlyChild = __webpack_require__(395);\nvar warning = __webpack_require__(35);\n\nvar createElement = ReactElement.createElement;\nvar createFactory = ReactElement.createFactory;\nvar cloneElement = ReactElement.cloneElement;\n\nif ({\"ENV\":\"server\"}.NODE_ENV !== 'production') {\n  var ReactElementValidator = __webpack_require__(393);\n  createElement = ReactElementValidator.createElement;\n  createFactory = ReactElementValidator.createFactory;\n  cloneElement = ReactElementValidator.cloneElement;\n}\n\nvar __spread = _assign;\n\nif ({\"ENV\":\"server\"}.NODE_ENV !== 'production') {\n  var warned = false;\n  __spread = function () {\n    {\"ENV\":\"server\"}.NODE_ENV !== 'production' ? warning(warned, 'React.__spread is deprecated and should not be used. Use ' + 'Object.assign directly or another helper function with similar ' + 'semantics. You may be seeing this warning due to your compiler. ' + 'See https://fb.me/react-spread-deprecation for more details.') : void 0;\n    warned = true;\n    return _assign.apply(null, arguments);\n  };\n}\n\nvar React = {\n\n  // Modern\n\n  Children: {\n    map: ReactChildren.map,\n    forEach: ReactChildren.forEach,\n    count: ReactChildren.count,\n    toArray: ReactChildren.toArray,\n    only: onlyChild\n  },\n\n  Component: ReactComponent,\n  PureComponent: ReactPureComponent,\n\n  createElement: createElement,\n  cloneElement: cloneElement,\n  isValidElement: ReactElement.isValidElement,\n\n  // Classic\n\n  PropTypes: ReactPropTypes,\n  createClass: ReactClass.createClass,\n  createFactory: createFactory,\n  createMixin: function (mixin) {\n    // Currently a noop. Will be used to validate and trace mixins.\n    return mixin;\n  },\n\n  // This looks DOM specific but these are actually isomorphic helpers\n  // since they are just generating DOM strings.\n  DOM: ReactDOMFactories,\n\n  version: ReactVersion,\n\n  // Deprecated hook for JSX spread, don't use this for anything.\n  __spread: __spread\n};\n\nmodule.exports = React;//# sourceMappingURL=data:application/json;charset=utf-8;base64,<huge base64 string omitted>");

And browser shows that SyntaxError is here:

process.env.NODE_ENV !== 'production' ? warning(warned, 'React.__spread is deprecated and should not be used. Use ' + 'Object.assign directly or another helper function with similar ' + 'semantics. You may be seeing this warning due to your compiler. ' + 'See https://fb.me/react-spread-deprecation for more details.') : void 0;

@Remper if you disable UglifyJsPlugin in your webpack config, do you get the same error?

@Aweary build succeeded, but then I get the same error when I open it in a browser: http://remper.ru/bug/

@Remper alright, I cloned down the project and I think I figured out the problem. It's not an issue with your ternary operator, it's an issue with how process.env.NODE_ENV is being replaced by DefinePlugin.

I removed NoErrorsPlugin from the config so the assets would still be emitted, and then ran it in the browser. The offending line is:

  {"ENV":"build"}.NODE_ENV !== 'production' ? warning(element, 'ReactComponentTreeHook: Missing React element for debugID %s when ' + 'building stack', id) : void 0;

The issue is with:

{"ENV":"build"}.NODE_ENV

Which is coming from:

        new webpack.DefinePlugin({
            // Environment helpers
            'process.env': {
                ENV: JSON.stringify(ENV)
            }
        }),

The problem here is that you're not replacing process.env.NODE_ENV, you're just replacing process.env with an object that has an ENV property. You can't do property access on an object literal definition, so it throws.

You can fix this by properly replacing instances of process.env.NODE_ENV by changing ENV to NODE_ENV

      new webpack.DefinePlugin({
            // Environment helpers
            'process.env': {
                NODE_ENV: JSON.stringify(ENV)
            }
        }),

I tested this locally and it built successfully 👍

@Aweary thanks a lot!

Was this page helpful?
0 / 5 - 0 ratings