Expose the partial Babel config for callers to load and mutate.#7472
Expose the partial Babel config for callers to load and mutate.#7472loganfsmyth merged 2 commits intobabel:masterfrom
Conversation
|
cc @benjamn @KyleAMathews since I've talked to you two about this a little |
|
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/7145/ |
|
Looks great! /cc @jquense |
|
Neat! |
| const { code, map, ast } = babel.transformFromAstSync(parsedAst, sourceCode, options); | ||
| ``` | ||
|
|
||
| ## babel.parse(code: string, [options?](#options): Object) |
There was a problem hiding this comment.
Does this return the AST or something else? Maybe we can add return types so I don't have to look up the code to see what this does. :)
There was a problem hiding this comment.
Sure, I'll add a note. Just realized we didn't document it when we actually landed that PR.
| * `name: string | void` - The name that the user gave the plugin instance, e.g. `plugins: [ ['env', {}, 'my-env'] ]` | ||
| * `file: Object | void` - Information about the plugin's file, if Babel knows it. | ||
| * `request: string` - The file that the user requested, e.g. `"@babel/env"` | ||
| * `resolved: string` - The full path of the resolved file, e.g. `"/tmp/node_modules/@babel/preset-env/lib/index.js"` |
There was a problem hiding this comment.
This is awesome, so in theory babel-loader can add every single plugin/preset as dependency (if coming from a file) so that webpack watch will trigger a change when one of them changes.
There was a problem hiding this comment.
Potentially, but since the presets aren't flattened, there are other plugins that aren't included here, so it wouldn't cover everything. Also since they are CommonJS, they'll still be cached by the module loader unless something also cleared that. I mostly exposed this since we already knew it and it seemed helpful for users. I'm figuring this will be good because they we can dump out a user's config in a human-readable format mostly.
| * `babelrc: string | void` - The path of the `.babelrc` file, if there was one. | ||
| * `babelignore: string | void` - The path of the `.babelignore` file, if there was one. | ||
| * `options: ValidatedOptions` - The partially resolved options, which can be manipulated and passed back to Babel again. | ||
| * `plugins: Array<ConfigItem>` - See below. |
There was a problem hiding this comment.
presets are not resolved to their plugins in this case?
There was a problem hiding this comment.
If they are not resolved (which I guess might be useful for some use cases) is there a way to "resolve" presets to plugins?
There was a problem hiding this comment.
There is babel.loadOptions to get the fully flattened options/plugin list, but honestly I don't think manipulating that list is a good idea since it means that you're potentially changing the behavior of a preset that wouldn't otherwise be changeable.
|
|
||
| export type { PartialConfig }; | ||
|
|
||
| class PartialConfig { |
There was a problem hiding this comment.
is there any value in this being a class?
also I havent ever understood the point of hiding "private" fields under public getters - would love to hear out the reasoning behind this structure, always seemed to me that it complicates a simple thing for no reason, especially that those getters do not have any additiona logic behind them
There was a problem hiding this comment.
Mostly because I wasn't sure if we might want to add other helper methods and stuff on here in the future, but you're totally right it isn't required right now.
There was a problem hiding this comment.
For instance I thought we might want a .hasFilesystemConfig() to do this.babelrc !== undefined || this.babelConfig !== undefined once we add the babel.config.js file.
|
This seems super useful for other tools 👏 |
| that callers will take the config's `.options`, manipulate it as then see fit | ||
| and pass it back to Babel again. | ||
|
|
||
| * `babelrc: string | void` - The path of the `.babelrc` file, if there was one. |
There was a problem hiding this comment.
Does loadPartialConfig only load the first .babelrc or it also loads its parents (when needed)? Also, what about babel.config.js?
There was a problem hiding this comment.
It basically does everything to know what the configured plugins and presets will be, without executing them, so that includes loading all config files, and any options passed in programmatically, and merging them all together into a single config object. It just skips actually calling the plugin/presets function, and flattening the presets themselves.
e69413a to
74ab279
Compare
|
Alright, I updated the I also updated the |
|
Sorry to capture this thread, but I'm a little confused what it the idiomatic way to load a config with the Node API. So the README for babel.transform(code, options, function(err, result) {
result; // => { code, map, ast }
});
We have Say I have a const opts = { filename: './src/foo.js' };
const { OptionManager } = require('babel-core');
console.log(new OptionManager().init(opts).plugins.length); // 0
const { loadOptions } = require('@babel/core');
// loadOptions(opts) same as (new require('@babel/core').OptionManager().init(opts))
console.log(loadOptions(opts).plugins.length); // 23It looks like the plugins are only resolved in Babel 7 (and only when I give it a Is the idiomatic way to load a config (e.g. is this return value of Should I use Thank you :) Update Or is the use case to make in-place changes to existing configs before the transformation (e.g. like here)? |
This PR exposes
.loadPartialConfigas a way to load the Babel configuration up to the point where the plugins and presets are all known, but have not yet loaded. It also exposes the path of the.babelrcand.babelignorefiles that Babel found, since a lot of tooling likes to toggle behavior based on whether the user has created a config file or not.The goal of this PR is to expose enough of Babel's config that we can avoid tooling feeling like they have to implement it themselves. I think this achieves that, but if there are cases where that isn't the case I'd love to hear them.
See the README in this PR for more information, but the core of this PR is that it exposes a new first-class instance type
ConfigItemthat is allowed inpluginsandpresetslists, and the results of.loadPartialConfigensures that each plugin and preset is aConfigItem. From the README:Each
ConfigItemexposes all of the information Babel knows. The fields are:value: {} | Function- The resolved value of the plugin.options: {} | void- The options object passed to the plugin.dirname: string- The path that the options are relative to.name: string | void- The name that the user gave the plugin instance, e.g.plugins: [ ['env', {}, 'my-env'] ]file: Object | void- Information about the plugin's file, if Babel knows it.request: string- The file that the user requested, e.g."@babel/env"resolved: string- The full path of the resolved file, e.g."/tmp/node_modules/@babel/preset-env/lib/index.js"Beyond that, tooling can manipulate the config however they'd like before passing the config back off to Babel again.