Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why do I have to put babel-presets inside .babelrc and webpack.config.js?

Ok. I am bootstraping a simple app. I am using flow.js. Presets that I use are babel-preset-2015, babel-preset-react and babel-preset-stage-0. I have to put same presets inside my .babelrc and inside my webpack.config for it all to work. If I for example romove them from webpack.config I get an error 'React is not defined'. If I remove .babelrc and babel-register I get an error because I use import and Flow.js annotation. Why is this happening? If I put presets inside webpack.config I should be able to delete .babelrc or vice verse. This is how my code looks now when it all works (minus some files that are not important for the 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'           ]         }       }     ]   } } 
like image 376
Igor-Vuk Avatar asked Apr 04 '17 11:04

Igor-Vuk


People also ask

Do you need Babel with Webpack?

If Babel is a translator for JS, you can think of Webpack as a mega-multi-translator that works with all kinds of languages (or assets). For example, Webpack often runs Babel as one of its jobs. Another example, Webpack can collect all your inline CSS styles in your Javascript files and bundle them into one.

Where do I put Babel presets?

Within a Babel config, if the preset is on npm, you can pass in the name of the preset and Babel will check that it's installed in node_modules already. This is added to the presets config option, which takes an array. Otherwise, you can also specify a relative or absolute path to your presets.

Why do we need Babel config JS?

Babel has two parallel config file formats which can be used together, or independently. . babelrc would be useful if you want to run certain transformations / plugins on a subset of files /directories. Maybe you have 3rd party libraries that you don't want to be transformed/changed by babel.


2 Answers

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

No, this is not the case. Specifying the presets in the webpack config will only affect webpack, everything else that uses babel (e.g. babel-node, babel-register, etc.) will not care about your webpack config and therefore doesn't see them.

The other way around does work. So you can remove the webpack presets options if you have a .babelrc, because babel-loader uses babel under the hood, which obviously respects the .babelrc.

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

The problem is that your .babelrc configuration is different from the configuration in the webpack config. The culprit is "passPerPreset": true. With this option every preset is applied individually without considering the others. And for this the order matters. From the babel docs - Plugin/Preset Ordering:

Preset ordering is reversed (last to first).

This means they will be applied in the following order: stage-0, react, es2015. As they are applied individually, react will transform the JSX to React.createElement, because React is in scope, and es2015 will transform just the import to _react2.default, therefore React is no longer defined. The entire diff between the two bundles is this:

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

There isn't much information about passPerPreset, but it was labelled experimental in the Release notes and you should probably avoid it altogether.

Although it would work if you put the react preset first in the list, I'd recommend to remove passPerPreset option, unless you have a very specific reason to use it.

{   "presets": [     "es2015",     "react",     "stage-0"   ] } 
like image 116
Michael Jungo Avatar answered Sep 17 '22 11:09

Michael Jungo


Try and modify your Loaders like

module: {     rules: [       {         test: /\.jsx?$/,         exclude: [/node_modules/],         use: [{           loader: 'babel-loader',           options: { presets: ['react','es2015', 'stage-0'] }         }],       }     ]   } 
like image 44
Shubham Khatri Avatar answered Sep 19 '22 11:09

Shubham Khatri