Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
kylemh opened this issue Feb 7, 2020 · 17 comments · May be fixed by #1000
Open

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

kylemh opened this issue Feb 7, 2020 · 17 comments · May be fixed by #1000

Comments

@kylemh
Copy link

kylemh commented Feb 7, 2020

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.

@dwiyatci
Copy link

dwiyatci commented Mar 13, 2020

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
Copy link

dwiyatci commented Mar 14, 2020

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.

@emilio-martinez
Copy link

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.

@nicolo-ribaudo
Copy link
Member

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

@kylemh
Copy link
Author

kylemh commented Mar 23, 2020

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).

@gaurav5430
Copy link

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

@arcanis
Copy link

arcanis commented Jul 13, 2020

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`)],
            },
          },
        ],
      },
    ],
  },
};

@kylemh
Copy link
Author

kylemh commented Jul 13, 2020

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

@thernstig
Copy link

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'],
          ],
        },
      },

@dwiyatci
Copy link

dwiyatci commented Dec 5, 2020

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

@thernstig
Copy link

thernstig commented Dec 5, 2020

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

@dwiyatci
Copy link

dwiyatci commented Dec 5, 2020

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

@thernstig
Copy link

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

@nicolo-ribaudo
Copy link
Member

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.

@dwiyatci
Copy link

dwiyatci commented Apr 9, 2021

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

@tehandyb
Copy link

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

@steverep
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants