web-dev-qa-db-ja.com

なぜ.babelrcとwebpack.config.jsの中にbabel-presetsを入れなければならないのですか?

OK。シンプルなアプリをブートストラップしています。 flow.jsを使用しています。私が使用するプリセットは、babel-preset-2015、babel-preset-react、およびbabel-preset-stage-0です。すべてを機能させるには、.babelrcとwebpack.configに同じプリセットを配置する必要があります。たとえば、webpack.configからそれらを削除すると、「React is not defined」というエラーが表示されます。 .babelrcとbabel-registerを削除すると、importとFlow.jsアノテーションを使用するためエラーが発生します。なんでこんなことが起こっているの? webpack.configにプリセットを配置すると、.babelrcまたはその逆を削除できるはずです。これは、すべてが機能するときのコードの外観です(質問にとって重要ではないファイルを除く)。

start-dev.js

require('babel-register')
require('./src/server/index.js')

index.js

/* @flow */

import Express from 'express'
import path from 'path'
import conf from '../conf/'

const APP_PORT: number = conf.APP_PORT
const PORT = process.env.PORT || APP_PORT

const app: Express = new Express()

// Middleware
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'ejs')
app.use(Express.static(path.join(__dirname, '../', 'client', 'dist')))

// Routes
app.get('*', function (req: Object, res: Object) {
  res.render('index')
})

app.listen(PORT, function () {
  console.log(`Express server is up on port ${PORT}`)
})

app.js

import React from 'react'
import ReactDOM from 'react-dom'

ReactDOM.render(
  <h1>First</h1>,
  document.getElementById('app')
)

package.json

{
  "scripts": {
    "start-dev": "set \"NODE_ENV=development\" && babel-node ./start-dev.js",
    "start": "set \"NODE_ENV=development\" && node ./start-dev.js",
    "flow": "./node_modules/.bin/flow check",
    "standard": "node_modules/.bin/standard --verbose | node_modules/.bin/snazzy"
  },
  "dependencies": {
    "ejs": "^2.5.6",
    "express": "^4.15.2",
    "react": "^15.4.2",
    "react-dom": "^15.4.2"
  },
  "devDependencies": {
    "babel-cli": "^6.24.0",
    "babel-core": "^6.24.0",
    "babel-eslint": "^7.2.1",
    "babel-loader": "^6.4.1",
    "babel-preset-es2015": "^6.24.0",
    "babel-preset-react": "^6.23.0",
    "babel-preset-stage-0": "^6.22.0",
    "babel-register": "^6.24.0",
    "eslint": "^3.18.0",
    "eslint-config-standard": "^7.1.0",
    "eslint-plugin-flowtype": "^2.30.4",
    "eslint-plugin-react": "^6.10.3",
    "flow-bin": "^0.42.0",
    "snazzy": "^6.0.0",
    "standard": "^9.0.2",
    "webpack": "^2.3.2"
  }
}

。babelrc

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

webpack.config.babel.js

'use strict'

import path from 'path'
const publicPath = path.resolve(__dirname, './src/client')

module.exports = {
  devtool: '#source-maps',
  performance: {
    hints: false
  },
  context: publicPath,
  entry: {
    bundle: './app.js'
  },
  output: {
    path: path.join(publicPath, 'dist'),
    filename: '[name].js',
    publicPath: '/dist/'
  },
  resolve: {
    extensions: ['.js', '.jsx']
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          presets: [
            'react',
            'es2015',
            'stage-0'
          ]
        }
      }
    ]
  }
}
17
Igor-Vuk

Webpack.configにプリセットを配置すると、.babelrcまたはその逆を削除できるはずです。

いいえ、そうではありません。 webpack configでプリセットを指定しても、webpackにのみ影響します。babelを使用する他のすべて(たとえば、babel-nodebabel-registerなど)は、webpackの設定を気にしないため、表示されません。

他の方法は機能します。 .babelrcは明らかにbabel-loaderを尊重するフードの下でbabelを使用するため、.babelrcがある場合は、webpackプリセットオプションを削除できます。

たとえば、webpack.configからそれらを削除すると、エラーReact is not definedが表示されます。

問題は、.babelrc設定がwebpack設定の設定と異なることです。犯人は"passPerPreset": trueです。このオプションを使用すると、他のプリセットを考慮することなく、すべてのプリセットが個別に適用されます。そして、このためには順序が重要です。 babel docs-Plugin/Preset Ordering から:

プリセットの順序が逆になります(最後から最初)。

これは、stage-0reactes2015の順に適用されることを意味します。これらは個別に適用されるため、reactはスコープ内にあるため、ReactはJSXをReact.createElementに変換し、es2015はインポートのみを_react2.defaultに変換します。したがって、Reactはもうありません定義済み。 2つのバンドル間の差分全体は次のとおりです。

@@ -9470,7 +9470,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
// var React = require('react')
// var ReactDOM = require('react-dom')

-_reactDom2.default.render(React.createElement(
+_reactDom2.default.render(_react2.default.createElement(
  'h1',
  null,
  'Juhuuuu'

passPerPresetについてはあまり情報がありませんが、 リリースノート で実験的なラベルが付けられているため、おそらく完全に回避する必要があります。

reactプリセットをリストの最初に置くと機能しますが、使用する特別な理由がない限り、passPerPresetオプションを削除することをお勧めします。

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

ローダーを次のように変更してみてください

module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: [/node_modules/],
        use: [{
          loader: 'babel-loader',
          options: { presets: ['react','es2015', 'stage-0'] }
        }],
      }
    ]
  }
1
Shubham Khatri