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
Plugin options #1833
Comments
Yeah, I talked about this a bit with @DmitrySoshnikov. The only way plugin options could be implemented is if the fourth visitor method parameter was a separate file and plugin-specific instance. Unfortunately changing that would be a breaking change (even though it's never actually documented anywhere, people are actively using it...) so yeah, it'll have to wait for 6.0.0. |
Yeah, for now we've been using extra: {
whatever: {
planB: true,
}
} And then access: state.opts.extra.whatever.planB; |
Thanks for the replies. @DmitrySoshnikov So are you saying you're satisfied with that as a permanent solution and don't mind plugins having access to each other's options? Or do you think it should be tightened up in the way @sebmck described when BC can be broken? @sebmck, would you be satisfied with plugins having access to each other's options? I don't particularly care about the CLI, but I know others do. Something additional would be needed to accomodate plugin options via the CLI, right? How about |
Not sure. Would probably need to group the options somehow in a similar vain to the visitor merging on
Plugin options could be set via {
"plugins": [
["plugin-name", { "options": "here" }]
]
}
CLI would work the same as Browserify: $ browserify -t [ babelify --option-here ] script.js |
Ok, so if that's going to be the case I think that's how the API should work also (as opposed to passing the options via
👍 That's what I was going to suggest. |
postcss has a set of guidelines for writing plugins which I find interesting. The config @sebmck proposed looks solid:
Browserify's API uses plugin/transform methods:
@jmm 's original example, could be expressed like this:
This syntax is fairly common, and |
(The ability to pass a function instead of a string isn't even documented yet.) I think to do it that way you'd have to use a different function that takes an options object and returns a function that takes a " export default function (opts) {
return function (babel) {};
};
// vs.
// For referencing by string
export default function (babel, opts) {}; So it should probably support: plugins: [
[someFunc, {options: 'here'}]
] Unless the API changes to: export a function that takes an options object and returns a function that takes a " There's also the matter of what's going to become of the |
I've been using environment variables for this, but it's not ideal. It does however have the benefit that it's trivial to override options from the CLI which is very useful. For instance, I'm writing a tracing plugin which allows something like this: export function someRoute (req, res) {
trace:info: "handling a request for `someRoute`";
const result = this.handle(req, res);
if (result instanceof Error) {
trace:error: "Error in someRoute", result;
}
return result;
} In my {
"plugins": [
{"name": "trace", "options": {"levels": ["error"]}}
]
} So that by default, only BABEL_PLUGIN_TRACE_LEVELS=info,error npm test or via command line options babel --plugin-trace-levels=info,error ./src It'd be really nice to have a standard way to do this. |
Hopefully I can clarify what I meant using some real-world examples. In babelify's readme, the author encourages the use of this syntax: // var browserify = require('browserify'), babelify = require('babelify')
browserify().transform(babelify.configure({
optional: ["es7.asyncFunctions"]
})) browserify -d -e script.js -t [ babelify --optional es7.asyncFunctions ] Yet, browserify's handbook uses this example: var b = browserify('main.coffee');
b.transform('coffeeify'); browserify -t coffeeify main.coffee > bundle.js In In reality, almost all plugins are individual npm packages, which are either required internally and in your projects main
|
This is wrong. Babel can take plugin instances AKA functions too. |
@sebmck Awesome!! I misinterpreted what @jmm said above and misinterpreted this in the source: export default class Plugin {
constructor(key: string, plugin: Object) {
Plugin.validate(key, plugin); but then I saw this: if (typeof plugin === "function") {
plugin = PluginManager.memoisePluginContainer(plugin);
plugin.key = key;
plugin.metadata.optional = true; so obviously plugins can be functions I'll just scratch that out... 😝 |
@RnbWd There are a number of ways to approach this, but I think the most straightforward baseline is to just have this: plugins: [['some-func', {/* opts */}]]
// and
plugins: [[someFunc, {/* opts */}]]
Here is the difference I'm talking about:
module.exports = function (babel, opts) {
babel.Plugin(/* ... */);
};
babel.transform(code, {
plugins: [['whatever', {some: 'thing'}]]
}); So far so good. But then you can't just do this without accounting for it somehow: plugins: [require('whatever')({some: 'thing'})] You can add extra logic to the plugin function to handle it, or provide a different method, like module.exports = function (opts) {
return function (babel) {
};
}; But I'm not sure what the advantage would be of doing any of those things instead of making the baseline what I suggested as the top (pass an array of
Hm?
Last I checked it was not, but I've heard new plugin documentation is in the pipeline. |
@sebmck responded to my comment above the previous one:
I support this syntax: plugins: [['some-func', {/* opts */}]] not this syntax: plugins: [[someFunc, {/* opts */}]] // how are options passed into the function? yet in plugins: [require('whatever')({some: 'thing'})]
// or
plugins: [['some-func', {/* opts */}]] I use both syntaxes 50/50 in |
A module that exports a function that returns an function is pretty hacky and a unique |
I know it can do it, the documentation still only covers strings though. sebmck's comments do make it sound as though passing a function will be supported and documented though.
The options are passed the same way as in the other case: in either case the function exported by the module accepts an options argument: // Same function in both cases
plugins: [['some-plugin', {/* opts */}]]
// or
plugins: [[require('some-plugin'), {/* opts */}]]
Those aren't equivalent by default (if both cases refer to the same module). The plugin would need to implement some internal logic to make those behave equivalently. Far more likely these are equivalent: plugin: [['some-plugin', {/* opts */}]]
// or
plugin: [[require('some-plugin'), {/* opts */}]] |
I have no idea how the |
In this example that would just make a broken module.
I'm not sure what seems so different about the two forms to you. It's just requiring the plugin module sooner or later.
It's loaded and invoked something like this: if (typeof plugin === 'string') plugin = require(plugin);
// Where `opts` are the opts you passed earlier
plugin(b, opts); |
Added. |
party! 👯 |
Awesome, thanks! |
Added where? Any info, commits, docs? |
@NekR I assume he means on the |
@jmm hmm.. thanks! I thought v6 development goes in |
I feel like plugins are going to be pretty hamstrung without an interface for passing options to them. There's nothing documented for that and as far as I know it doesn't currently exist. If that's correct, perhaps 6.0 would be a good opportunity to introduce this.
Example:
Thoughts?
The text was updated successfully, but these errors were encountered: