reactjs - 为什么我必须将 babel-presets 放入 .babelrc 和 webpack.config.js 中?

标签 reactjs webpack babeljs

好的。我正在引导一个简单的应用程序。我正在使用 flow.js。我使用的预设是 babel-preset-2015、babel-preset-react 和 babel-preset-stage-0。我必须将相同的预设放入 .babelrc 和 webpack.config 中才能使其正常工作。例如,如果我从 webpack.config 中删除它们,我会收到错误“React 未定义”。如果我删除 .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'
          ]
        }
      }
    ]
  }
}

最佳答案

If I put presets inside webpack.config I should be able to delete .babelrc or vice verse.

不,事实并非如此。在 webpack 配置中指定预设只会影响 webpack,其他所有使用 babel 的东西(例如 babel-node、babel-register 等)都不会关心你的 webpack配置,因此看不到它们。

反之亦然。因此,如果您有 .babelrc,您可以删除 webpack 预设选项,因为 babel-loader 在底层使用 babel,这显然尊重 .babelrc.

If I for example remove them from webpack.config I get an error React is not defined.

问题是您的 .babelrc 配置与 webpack 配置中的配置不同。罪魁祸首是"passPerPreset": true。使用此选项,每个预设都会单独应用,而不考虑其他预设。为此,顺序很重要。来自 babel docs - Plugin/Preset Ordering :

Preset ordering is reversed (last to first).

这意味着它们将按以下顺序应用:stage-0reactes2015。当它们单独应用时,react 会将 JSX 转换为 React.createElement,因为 React 在范围内,并且 es2015 code> 仅将导入转换为 _react2.default,因此不再定义 React。两个 bundle 之间的完整差异如下:

@@ -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 的信息并不多,但它在 Release notes 中被标记为实验性的。你可能应该完全避免它。

虽然如果您将 react 预设放在列表中的第一位就可以了,但我建议删除 passPerPreset 选项,除非您有非常具体的使用原因它。

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

关于reactjs - 为什么我必须将 babel-presets 放入 .babelrc 和 webpack.config.js 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43206062/

相关文章:

jquery - 如何在 angular2 webpack 中使用 jquery?获取 $ not defined

javascript - ES6 导入并要求无法与 gulp/browserify/babelify 正常工作

javascript - redux react 错误 : Actions must be plain objects

javascript - 如何将文件编码为 base64,然后使用 JS 作为多部分文件上传到后端 api?

javascript - npm 链接不适用于 angular-cli 创建的项目

webpack - ProgressPlugin TypeError : Cannot read property 'tap' of undefined

javascript - 使用 babel by gulp-watch 转换为 ES5 不起作用

javascript - 语法错误 : Unexpected identifier with mocha and babel

javascript - 如何重写将另一个类扩展为功能组件的 React 类?

javascript - 如果在 onRowSelection 中使用 setState,则响应 : Material-ui tableRow can not choose,