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

Allow to replace options in configuration callbacks #300

Merged
merged 3 commits into from
Apr 14, 2018

Conversation

Lyrkan
Copy link
Collaborator

@Lyrkan Lyrkan commented Apr 12, 2018

This PR closes #298 by using the return value of callback functions (for loaders/plugins) as options if it is an object.

For instance:

Encore.configureUglifyJsPlugin((options) => {
    return {
        ...options,
        beautify: true
    };
});

Copy link
Member

@weaverryan weaverryan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, VERY complete work on this - nice job @Lyrkan :). Thoughts on how to document this? We could update the jsdoc above every method in index.js with something like this:

Encore.configureExtractTextPlugin((options) => {
    options.ignoreOrder = true;

    // or, return the exact options
    // return { ignoreOrder: true }
});

I'm not sure. It makes it a lot longer, and most users don't need this. Another idea would be to start requiring returning as the ONLY way (and deprecate returning nothing). It would simplify the example, and it would be obvious for expert users that they could, of course, return a totally different/custom object.

@Lyrkan
Copy link
Collaborator Author

Lyrkan commented Apr 12, 2018

I'm not sure. It makes it a lot longer, and most users don't need this.

Yeah, that's why I didn't do it, but I don't mind adding it if you think that's needed.
However in this case maybe we should also warn the user that returning a brand new object can remove some default options that are set by Encore.

Another idea would be to start requiring returning as the ONLY way (and deprecate returning nothing). It would simplify the example, and it would be obvious for expert users that they could, of course, return a totally different/custom object.

I'm not sure about that, you'll still have to use the "options" param since in many cases it contains some values that are set by Encore. Doing return { ...options, ignoreOrder: true } (and that's if you use a Node version that supports object spread...) may be less easy to understand than just options.ignoreOrder = true.

@stof
Copy link
Member

stof commented Apr 12, 2018

I suggest creating a small utility instead of duplicating the same logic everywhere:

const processOptions = require('./util/process_options');

const options =  { ... };

loaders.push({
    loader: 'postcss-loader',
    options: processOptions(webpackConfig.postCssLoaderOptionsCallback, options)
};
module.exports = function (configurationCallback, options) {
    const result = configurationCallback.apply(options, [options]); // could even use .call to avoid creating a temporary array)

    if (typeof result === 'object') {
        return result;
    }

    return options;
}

Another idea would be to start requiring returning as the ONLY way (and deprecate returning nothing). It would simplify the example, and it would be obvious for expert users that they could, of course, return a totally different/custom object.

I'm not sure about that, you'll still have to use the "options" param since in many cases it contains some values that are set by Encore. Doing return { ...options, ignoreOrder: true } (and that's if you use a Node version that supports object spread...) may be less easy to understand than just options.ignoreOrder = true.

Thus, it becomes even harder in the case of nested options.

@stof
Copy link
Member

stof commented Apr 12, 2018

The great thing is that we have the same signature for all our configuration callbacks (and centralizing the feature would ensure it stays true in the future). So the doc could have one section describing the different supported ways, and have all other sections showing one of them (with a link to the full doc about config callbacks).

@stof
Copy link
Member

stof commented Apr 12, 2018

btw, returning the options could still be done with simple editions:

Encore.configureExtractTextPlugin((options) => {
    options.ignoreOrder = true;

    return options;
});

this could allow dropping support for not returning in the future (and throwing an exception if the callback does not return anything), but this would require a deprecation period first anyway.

@Lyrkan
Copy link
Collaborator Author

Lyrkan commented Apr 12, 2018

@stof I changed it in order to use your method (+ tweaked the vue-loader part a bit).

You're also right about the fact that you could still do options.ignoreOrder = true followed by a return options but I still think that's a bit more error-prone. We'll throw an error if the method doesn't return anything but won't notice if the user inadvertently creates a new object that doesn't contain the default options.

@@ -25,21 +26,18 @@ module.exports = function(plugins, webpackConfig) {
manifestPrefix = webpackConfig.publicPath.replace(/^\//, '');
}

const manifestPluginOptions = {
let manifestPluginOptions = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be reverted to const

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I missed that one

Copy link
Member

@weaverryan weaverryan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok - let's keep both ways - it would be easy for us to deprecate not returning a value later.

I think Stof is correct about documenting "globally" somewhere that you can return a value from the callback. Maybe under the FAQ... for lack of a better place?

@weaverryan
Copy link
Member

Thank you @Lyrkan!

@weaverryan weaverryan merged commit 3dfc787 into symfony:master Apr 14, 2018
weaverryan added a commit that referenced this pull request Apr 14, 2018
…kan)

This PR was squashed before being merged into the master branch (closes #300).

Discussion
----------

Allow to replace options in configuration callbacks

This PR closes #298 by using the return value of callback functions (for loaders/plugins) as options if it is an object.

For instance:

```js
Encore.configureUglifyJsPlugin((options) => {
    return {
        ...options,
        beautify: true
    };
});
```

Commits
-------

3dfc787 Revert a forgotten 'let' to a 'const'
ef992c1 Replace duplicated 'options callback' logic by an utility method
ecb623c Allow to replace options in configuration callbacks
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 this pull request may close these issues.

Allow replacing options in configuration callbacks
3 participants