babel-loader icon indicating copy to clipboard operation
babel-loader copied to clipboard

Add explicit note in README that `.babelrc` and `babel.configs.js` are consumed automatically

Open kylemh opened this issue 5 years ago • 17 comments

I'm submitting a feature request I was fairly certain this was a thing, but it took me a long time to confirm to coworkers (and discover the nuances of using .babelrc vs. babel.config.js in the context babel-loader).

I think it's a good idea to document the fact that the config file is read automatically.

kylemh avatar Feb 07 '20 23:02 kylemh

What is more confusing to me is that when you have both babel.config.js (or .babelrc) and options in the loader being set at the same time, how does it actually behave? Is it overridden - if so, which options config is gonna win? Or are they merged? I've tried to read the source code but still confused 😅

Perhaps @loganfsmyth can give some enlightenments on this?

dwiyatci avatar Mar 13 '20 22:03 dwiyatci

Please ignore my remark. After digging down a bit deeper, babel-loader uses babel.loadPartialConfig underneath. So for each preset or plugin that's already specified in babel.config.js or .babelrc, its options will be overridden by the options of the babel-loader that corresponds to that particular preset or plugin.

dwiyatci avatar Mar 14 '20 17:03 dwiyatci

On that note, documenting that options passed to babel-loader will pretty much take precedence over those in babel.config.js or .babelrc would be great to have documented. I spent about an hour or so debugging until I realized the same thing that @dwiyatci pointer out.

emilio-martinez avatar Mar 23 '20 12:03 emilio-martinez

Maybe we should link https://babeljs.io/docs/en/options#merging in the readme, and improve that section of the docs on the website?

nicolo-ribaudo avatar Mar 23 '20 14:03 nicolo-ribaudo

Even that documentation isn't very explicit by itself, IMO. This helps explain how multiple configs resolve against each other, but maybe a small sentence on the fact that root-level Babel config files are picked up implicitly when you have root-level webpack config using babel-loader (and that there are other situations where configs are picked up automatically).

kylemh avatar Mar 23 '20 16:03 kylemh

Just stumbled on this issue. Would be great to get this added to the documentation.

gaurav5430 avatar Jun 22 '20 16:06 gaurav5430

Something that isn't quite clear to me: how does babelrc: false interact with babel.config.js? I've set the following config, but it doesn't seem to disable babel.config.js (however, it properly disable .babelrc.js). I don't know if that's a bug or not 🤔

Edit: adding configFile: false on top of babelrc: false works 🎆

module.exports = {
  entry: { main: ["./index.tsx?transpiled"] },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        resourceQuery: /\?transpiled$/,
        use: [
          { loader: require.resolve(`raw-loader`) },
          {
            loader: require.resolve(`babel-loader`),
            options: {
              babelrc: false,
              presets: [require.resolve(`@babel/preset-typescript`)],
            },
          },
        ],
      },
    ],
  },
};

arcanis avatar Jul 13 '20 13:07 arcanis

@nicolo-ribaudo no other maintainer has commented, so I apologize for @ing you ❤️.

I'll contribute a PR to resolve this, but I need feedback first on ^

kylemh avatar Jul 13 '20 14:07 kylemh

I am also utterly confused by this, as there is no documentation describing this and spending trial & error time is not ideal.

Please ignore my remark. After digging down a bit deeper, babel-loader uses babel.loadPartialConfig underneath. So for each preset or plugin that's already specified in babel.config.js or .babelrc, its options will be overridden by the options of the babel-loader that corresponds to that particular preset or plugin.

@dwiyatci what happens in this instance?

babel.config.js

module.exports = {
  // Plugins run before presets
  plugins: [
    ['./someproj/node_modules/@babel/plugin-transform-spread'],
    ['./someproj/node_modules/@babel/plugin-proposal-object-rest-spread'],
    [
      './someproj/node_modules/@babel/plugin-proposal-decorators',
      { legacy: true },
    ],
    ['./someproj/node_modules/@babel/plugin-proposal-class-properties'],
  ],
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          node: 'current',
        },
      },
    ],
  ],
};

webpack.config.js

      {
        test: /\.js$/,
        loader: 'babel-loader',
        options: {
          plugins: [
            ['@babel/plugin-proposal-decorators', { legacy: true }],
            ['@babel/plugin-proposal-class-properties'],
            ['@babel/plugin-proposal-object-rest-spread'],
            ['@babel/plugin-transform-spread'],
          ],
        },
      },

thernstig avatar Dec 05 '20 10:12 thernstig

@thernstig Well, based on my comment above, nothing will be overridden because the plugin options you specified for each plugin in babel-loader options in your webpack.config.js are identical with the ones in your babel.config.js. In this case, you might as well simplify your webpack config to:

{
  test: /\.js$/,
  loader: 'babel-loader',
}

To make sure, you can debug it yourself: in your node_modules/babel-loader/lib/index.js, just put a break point after this line:

const config = yield loadPartialConfigAsync(injectCaller(programmaticOptions, this.target));

...or if you don't fancy breakpoint, simply console.log to see what the options for each plugin are:

console.log({ plugins: JSON.stringify(config.options.plugins) });

UPDATE: if you use webpack 5 with persistent caching (to filesystem), you probably need to comment out that webpack's cache: {} config momentarily for the debug line to kick-in.

dwiyatci avatar Dec 05 '20 14:12 dwiyatci

@dwiyatci If you look again, you notice I also have a presets in there, hence my question. So it is not clear what happens with that one in this case for me. But I assume then that plugins in webpack will take precedence, and that presets will be taken from webpack as well? And what if the plugins options are not identical?

edit: I suppose my question is both rhetorical and actually asking, since I both wanted to also highlight these things are not described in the docs and that I was hoping you already knew the answer 😄

thernstig avatar Dec 05 '20 17:12 thernstig

@thernstig Whoops. Sorry, I missed that. 😅 Yeah, pretty much for presets, too. At any rate, if you don't wanna do trial-and-error or assume, just see it yourself by checking that console.log({ options: JSON.stringify(config.options) }); (while it's not documented) – that'd be your single source of truth containing options for Babel that babel-loader passes to babel.transform.

dwiyatci avatar Dec 05 '20 17:12 dwiyatci

@dwiyatci I dug some more in my case, and this is what I found out.

I have these files: client/webpack.config.dev.js babel.config.js

The config for babel-loader and the options in there takes no account of babel.config.js. So if I remove the options from the babel-loader the output of your suggestion gives { plugins: '[]' } even though babel.config.js contains a lot of plugin config.

Thus, this is a mess to know what to expect unless printing.

thernstig avatar Apr 09 '21 12:04 thernstig

You can try running BABEL_SHOW_CONFIG_FOR=./src/index.js npm run build (replace npm run build with your build command) to see what config Babel is resolving when compiling the src/index.js file.

nicolo-ribaudo avatar Apr 09 '21 12:04 nicolo-ribaudo

@thernstig Feels like I just want to forget all of these... Hahahah

dwiyatci avatar Apr 09 '21 15:04 dwiyatci

This was causing an issue for me too, I set the babel loader in my webpack config to use some config for treeshaking, but I had a babel.config.js that was not setup for treeshaking and that config overrode the treeshaking config I set in babel-loader! Took me a while to realize the babel-loader options get overridden by babel.config.js

tehandyb avatar Sep 29 '21 17:09 tehandyb

A closely related documentation issue would be the description of the cacheIdentifier option:

cacheIdentifier: Default is a string composed by the @babel/core's version, the babel-loader's version, the contents of .babelrc file if it exists, and the value of the environment variable BABEL_ENV with a fallback to the NODE_ENV environment variable. ...

It makes it sound like using babel.config.js and/or the options property in the Webpack config play no part in the default cache identifier, but I'm pretty sure that's not the case.

steverep avatar Jul 24 '23 17:07 steverep