web-dev-qa-db-fra.com

pourquoi dois-je mettre babel-presets dans .babelrc et webpack.config.js?

D'accord. Je suis bootstraping une application simple. J'utilise flow.js. Les préréglages que j'utilise sont babel-preset-2015, babel-preset-react et babel-preset-stage-0. Je dois mettre les mêmes préréglages dans mon .babelrc et dans mon webpack.config pour que tout fonctionne. Si, par exemple, je les trouve dans webpack.config, le message d'erreur «Réagir n'est pas défini». Si je supprime .babelrc et babel-register, j'obtiens une erreur car j'utilise import et l'annotation Flow.js. Pourquoi cela arrive-t-il? Si je mets des presets dans webpack.config, je devrais être capable de supprimer .babelrc ou vice versa. Voici à quoi ressemble mon code lorsque tout fonctionne (moins certains fichiers qui ne sont pas importants pour la question).

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'
          ]
        }
      }
    ]
  }
}
10
Igor-Vuk

Si je mets des presets dans webpack.config, je devrais être capable de supprimer .babelrc ou vice-versa.

Non, ce n'est pas le cas. La spécification des préréglages dans la configuration Webpack n’affectera que Webpack. Tout le reste utilisant babel (par exemple, babel-node, babel-register, etc.) ne se souciera pas de votre configuration Webpack et ne les verra donc pas.

L'inverse fonctionne. Vous pouvez donc supprimer les options de préconfiguration Webpack si vous avez un .babelrc, car babel-loader utilise babel sous le capot, qui respecte évidemment le .babelrc.

Si, par exemple, je les supprime de webpack.config, j'obtiens une erreur React is not defined.

Le problème est que votre configuration .babelrc est différente de celle de la configuration Webpack. Le coupable est "passPerPreset": true. Avec cette option, chaque préréglage est appliqué individuellement sans tenir compte des autres. Et pour cela, l'ordre compte. À partir de Babel Docs - Plugin/Preset Ordering :

L'ordre des préréglages est inversé (du premier au premier).

Cela signifie qu'ils seront appliqués dans l'ordre suivant: stage-0, react, es2015. Comme ils sont appliqués individuellement, react transformera le fichier JSX en React.createElement, car React est dans la portée et es2015 transformera uniquement l'importation en _react2.default; par conséquent, React n'est plus défini. Le diff entier entre les deux paquets est la suivante:

@@ -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'

Il n’ya pas beaucoup d’informations sur passPerPreset, mais il a été qualifié de expérimental dans Notes de publication et vous devriez probablement l’éviter complètement.

Bien que cela fonctionne si vous mettez le paramètre react en premier dans la liste, je vous recommande de supprimer l’option passPerPreset, à moins que vous n’ayez une raison très précise de l’utiliser.

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

Essayez et modifiez vos chargeurs comme

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