babel-loader
babel-loader copied to clipboard
Add explicit note in README that `.babelrc` and `babel.configs.js` are consumed automatically
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.
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?
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.
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.
Maybe we should link https://babeljs.io/docs/en/options#merging in the readme, and improve that section of the docs on the website?
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).
Just stumbled on this issue. Would be great to get this added to the documentation.
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`)],
},
},
],
},
],
},
};
@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 ^
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-loaderusesbabel.loadPartialConfigunderneath. So for each preset or plugin that's already specified inbabel.config.jsor.babelrc, its options will be overridden by theoptionsof thebabel-loaderthat 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 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 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 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 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.
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.
@thernstig Feels like I just want to forget all of these... Hahahah
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
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.