How to set up Babel 6 stage 0 with React and Webpa

2019-01-31 05:15发布

问题:

My understanding from the docs

I see that Babel 6 has three presets for now: es2015, react and stage-x. I read that I can set those in .babelrc like so:

{
  "presets": ["es2015", "react", "stage-0"]
}

or directly in package.JSON like so:

{
  ...,
  "version": x.x.x,
  "babel": {
    "presets": ["es2015", "react", "stage-0"]
  },
  ...,
}

I can further use babel-loader with webpack like this:

loader: 'babel?presets[]=es2015'


My problem

So to compile everything nice and clean I'm adding babel-loader, which has just been updated to work with Babel6, to the webpack config like this:

module.exports = function(options) {
  var jsLoaders = ['babel?presets[]=es2015'];
  [...]
    loaders: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loaders: jsLoaders
      },
      {
        test: /\.jsx$/,
        exclude: /node_modules/,
        loaders: options.production ? jsLoaders : ['react-hot'].concat(jsLoaders)
      },
      [...]


Now when I compile without .babelrc in root or presets options set in package.JSON, i.e. only with the babel-loader es2015 preset set in the webpack config I get an unexpected token error about static propTypes in my React component class:

ERROR in ./app/components/form/index.jsx
Module build failed: SyntaxError: /Library/WebServer/Documents/yarsk.test/app/components/form/index.jsx: Unexpected token (19:19)
  17 | // ES6 React Component:
  18 | export default class SurveyForm extends Component {
> 19 |   static propTypes = {
     |                    ^

On GitHub I got told this is a stage-1 feature, namely transform-class-properties. So I would like to implement stage-0 right away.
BUT
When I do so by adding .babelrc or defining package.JSON like above I get a very weird build fail error:

ERROR in ./app/components/form/index.jsx
Module build failed: Error: /Library/WebServer/Documents/yarsk.test/app/components/form/index.jsx: We don't know what to do with this node type. We were previously a Statement but we can't fit in here?
    at NodePath.insertAfter (/Library/WebServer/Documents/yarsk.test/node_modules/babel-traverse/lib/path/modification.js:181:13)
    at NodePath.replaceWithMultiple (/Library/WebServer/Documents/yarsk.test/node_modules/babel-traverse/lib/path/replacement.js:92:8)
    at handleClassWithSuper (/Library/WebServer/Documents/yarsk.test/node_modules/babel-plugin-transform-class-constructor-call/lib/index.js:80:10)
    at PluginPass.Class (/Library/WebServer/Documents/yarsk.test/node_modules/babel-plugin-transform-class-constructor-call/lib/index.js:101:11)
    at newFn (/Library/WebServer/Documents/yarsk.test/node_modules/babel-traverse/lib/visitors.js:233:27)
    at NodePath._call (/Library/WebServer/Documents/yarsk.test/node_modules/babel-traverse/lib/path/context.js:72:18)
    at NodePath.call (/Library/WebServer/Documents/yarsk.test/node_modules/babel-traverse/lib/path/context.js:44:17)
    at NodePath.visit (/Library/WebServer/Documents/yarsk.test/node_modules/babel-traverse/lib/path/context.js:102:12)
    at TraversalContext.visitQueue (/Library/WebServer/Documents/yarsk.test/node_modules/babel-traverse/lib/context.js:151:16)
    at TraversalContext.visitSingle (/Library/WebServer/Documents/yarsk.test/node_modules/babel-traverse/lib/context.js:111:19)
    at TraversalContext.visit (/Library/WebServer/Documents/yarsk.test/node_modules/babel-traverse/lib/context.js:195:19)
    at Function.traverse.node (/Library/WebServer/Documents/yarsk.test/node_modules/babel-traverse/lib/index.js:139:17)
    at NodePath.visit (/Library/WebServer/Documents/yarsk.test/node_modules/babel-traverse/lib/path/context.js:106:22)
    at TraversalContext.visitQueue (/Library/WebServer/Documents/yarsk.test/node_modules/babel-traverse/lib/context.js:151:16)
    at TraversalContext.visitMultiple (/Library/WebServer/Documents/yarsk.test/node_modules/babel-traverse/lib/context.js:106:17)
    at TraversalContext.visit (/Library/WebServer/Documents/yarsk.test/node_modules/babel-traverse/lib/context.js:193:19)
    at Function.traverse.node (/Library/WebServer/Documents/yarsk.test/node_modules/babel-traverse/lib/index.js:139:17)
 @ ./app/index.jsx 9:0-28

Or in short: Module build failed: Error: /.../index.jsx: We don't know what to do with this node type. We were previously a Statement but we can't fit in here?

This is where I'm stuck. I wrote this component with Babel5 when I was able to compile with babel-loader like this and everything worked fine:

loader: 'babel?optional[]=runtime&stage=0

Now I'm getting the mentioned errors compiling.

  • Is this a babel-loader issue, or a babel issue?
  • Where do I have to configure stage-0 so that it won't throw errors?


Update

When compiling with presets set and using the mentioned workaround for the class export bug (must not export class until after creating it) the order of the set presets changes the error message. When I set stage-0 first the error now is 'this' is not allowed before super() (This is an error on an internal node. Probably an internal error) When I put stage-0 second or third I get the message about syntax error from above.


Latest

For the latest advances regarding these bugs see my post or the new babel issue tracker on phabricator for more. (Basically compiling is fixed as of 6.2.1 but there's other things happening now)

All the bugs mentioned in this article are completely fixed as of Babel 6.3.x. Please update your dependencies if you're still having issues.

回答1:

The two pretty heavy bugs I ran into here, namely the direct export of an ES6 class with a static property and a problem with the ES6 constructor are discussed in the answers of this thread and can be found on GitHub explicitly here (export bug) and here (constructor bug). (GitHub Issue Tracker has been closed and issues, bugs and requests have moved here.)

These are both officially confirmed bugs, fixed since Babel 6.3.17

(Maybe one or two earlier, not before 6.3.x, this is the version I'm on and everything is working as it was with Babel5. Happy coding everyone.)


(For the records:)

So if you get the following error message in the CLI:

We don't know what to do with this node type. We were previously a Statement but we can't fit in here?

Chances are you are exporting an ES6 class with a static property like this or in a similar manner (note that this doesn't seem to be connected to the class being extended anymore but rather to a class having a static property):

import React, { Component, PropTypes } from 'react'

export default class ClassName extends Component {
  static propTypes = {...}
  // This will not get compiled correctly for now, as of Babel 6.1.4
}

The simple workaround as mentioned by Stryzhevskyi and several people on GitHub:

import React, { Component, PropTypes } from 'react'

class ClassName extends Component {
  static propTypes = {...}
}
export default ClassName // Just export the class after creating it



The second issue is about the following error:

'this' is not allowed before super() (This is an error on an internal node. Probably an internal error)

Despite being a legit rule as pointed out by Dominic Tobias this is a confirmed bug where it appears that extended classes having their own properties will throw this or a similar message. As for now I have not seen any workarounds for this one. Lots of people rolled back to Babel5 for this reason for now (as of 6.1.4).

Supposedly this was fixed with the release of Babel 6.1.18 (see above GitHub issue) but people, me included, still see the same exact problem happening.


Also take note that for now the order in which you load the babel presets stage-x, react and es2015 seems to be important and may change your output.


As of Babel 6.2.1

both of these bugs are fixed, code compiles fine. But... there is still another one that probably affects a lot of people working with react, that throws ReferenceError: this hasn't been initialised - super() hasn't been called at runtime. Referenced here. Stay tuned...


Completely fixed since Babel 6.3.17

(Maybe one or two earlier, not before 6.3.x, this is the version I'm on and everything is working as it was with Babel5. Happy coding everyone.)



回答2:

Try to replace your export with such construction:

class SurveyForm extends Component {/*implementation*/}
export default SurveyForm


回答3:

Here is a working example with Babel 6, React, Webpack and Sequelize:

https://github.com/BerndWessels/react-webpack

Basically this is the .babelrc

{
  "presets": [
    "es2015",
    "react",
    "stage-0"
  ],
  "env": {
    "development": {
      "plugins": [
        "babel-relay-plugin-loader",
        [
          "react-transform",
          {
            "transforms": [
              {
                "transform": "react-transform-hmr",
                "imports": [
                  "react"
                ],
                "locals": [
                  "module"
                ]
              },
              {
                "transform": "react-transform-catch-errors",
                "imports": [
                  "react",
                  "redbox-react"
                ]
              }
            ]
          }
        ]
      ]
    },
    "production": {
      "plugins": [
        "babel-relay-plugin-loader"
      ]
    }
  }
}

and these are the module versions

babel-core@6.3.17
babel-loader@6.2.0
babel-plugin-react-transform@2.0.0-beta1
babel-preset-es2015@6.3.13
babel-preset-react@6.3.13
babel-preset-stage-0@6.3.13

That works for me.



回答4:

After having the same issues, I was able to get this working with React using the below WebPack config.

module.exports = {
  entry: './app/Index.js',
  output: { path: __dirname, filename: 'dist/bundle.js' },
  module: {
    loaders: [
        {
            test: /\.js$/,
            loader: 'babel',
            query: {
                presets: ['react']
            }
        }
    ]
  }
};

I also needed to install babel-preset-react too.

npm install --save-dev babel-preset-react

EDIT: Of course you might still need to also include the ES2015 preset if you are writing ES6 as well.

Babel Presets can be found here: https://github.com/babel/babel/tree/development/packages



回答5:

Have you tried?:

presets: [{
    plugins: [
        'transform-class-properties'
    ]
}, 'stage-0', 'es2015', 'react']


回答6:

Have you tried using just stage-1?

Using query property worked for me.

```
module: {
  loaders: [{
    test: /\.jsx?$/, 
    loader: 'babel',
    query: {
      presets: ['es2015', 'stage-1', 'react']
    }
  }]
}
```

Of course, I haven't been able to use .babelrc and babel options in package.json. Still trying to figure out babel-*v6.0