-
Notifications
You must be signed in to change notification settings - Fork 234
Feature: allow specifying to use before or after other use #42
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea!
Have left a few comments below. I was also wondering whether this functionality would be useful for plugins? eg ScriptExtHtmlPlugin
must be after htmlTemplate
, which in Neutrino it is by default, but with Treeherder we're needing to add multiple extra htmlTemplate
, which end up being placed after ScriptExtHtmlPlugin
?
README.md
Outdated
@@ -750,6 +750,50 @@ config.module | |||
.options({ presets: ['babel-preset-es2015'] }); | |||
``` | |||
|
|||
#### Config module rules use before | |||
|
|||
Specify to that one `use` should be used before another `use` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this meant to be s/to that/that/ ? (And the same below?)
src/Rule.js
Outdated
|
||
if (_before && uses.includes(_before)) { | ||
uses.splice(uses.indexOf(name), 1); | ||
uses.splice(Math.max(uses.indexOf(_before), 0), 0, name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the Math.max()
needed? presumably the only time it's required is if uses.indexOf(_before) < 0
(eg -1 for not found), however the uses.includes(_before)
presumably rules out that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My mistake, this was leftover from a different implementation version.
src/Rule.js
Outdated
|
||
names.forEach(name => { | ||
const { _before, _after } = useEntries[name]; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need a check to ensure both _before
and _after
are not set for the same rule, and fail loudly if so? (And a mention in the docs?) Since currently if both are set, the _after
clobbers the splices made by the _before
handling.
README.md
Outdated
@@ -750,6 +750,50 @@ config.module | |||
.options({ presets: ['babel-preset-es2015'] }); | |||
``` | |||
|
|||
#### Config module rules use before |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other sections use a naming of form "Config module rules uses (loaders): modifying options" - I don't have a preference as to which to use, but wanted to note that this wasn't consistent with them, in case this wasn't intentional.
d397e8f
to
bcab25a
Compare
@edmorley Great feedback! In order to make ordering more generic for usage with more than |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah some good cleanup here now too!
I've left some initial comments - though would like to take another look with fresh eyes once it's updated. If it's not too much of a pain to split it up into say 3 commits (one for the variable name changes, one for adding the omit feature, and one for the before/after handling) that would make review a lot easier, especially given I'm less familiar with the codebase. I use SourceTree for easy line by line commit splitting/staging if that's of any use.
This also has conflicts with the README changes on master, could you rebase? :-)
README.md
Outdated
// returns: Object, undefined if empty | ||
entries() | ||
```` | ||
|
||
```js | ||
// Provide an object which maps its properties and values | ||
// into the backing Map as keys and values. | ||
// into the backing Map as keys and values. Can specify | ||
// an array of keys to omit from the merge. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I read this I was imagining the keys being omitted might be those on the original object (eg so a new array could be passed in for a particular property and not just merged in with the existing array). However from reading the source below the opposite appears to be the case? (I'm struggling at quick glance to tell though due to the larger diff and not having spent long looking at it) Either way I think it would be good to clarify in this comment :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'll try to phrase this better. The omit
property is supposed to be an array of keys that should be excluded from merging into the config, e.g. the following would do nothing.
config.merge({ devtool: 'source-map' }, ['devtool'])
README.md
Outdated
#### Config plugins: ordering before | ||
|
||
Specify that the current `plugin` context should operate before another named `plugin`. | ||
You cannot use `before()` and `after()` on the same plugin. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/cannot use/cannot use both/ perhaps? (And in the other instances below)
|
||
config | ||
.plugin('html-template') | ||
.use(HtmlWebpackTemplate) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The indentation here is inconsistent with some of the other existing entries - this indents the .use()
one level deeper than .plugin()
, the others don't. Thoughts on which is preferred?
src/ChainedMap.js
Outdated
|
||
after(name) { | ||
if (this.__after) { | ||
throw new Error(`Unable to set after(${JSON.stringify(name)}) with existing value for before`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be after(...)
or .after(...)
? (And same for before(...)
)
I can't decide :-)
src/ChainedMap.js
Outdated
|
||
merge(obj, omit = []) { | ||
if (obj.before && obj.after) { | ||
throw new Error(`Unable to merge before: ${JSON.stringify(obj.before)} and after: ${JSON.stringify(obj.after)} on the same object`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this case ever be hit given there are already checks at the time of using before()
and after()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, when merging in configuration from an object, these can be set by the user:
config.merge({
module: {
rule: {
compile: {
use: {
cache: {
loader: 'cache-loader',
before: 'babel'
}
}
}
}
}
})
@@ -39,11 +39,11 @@ module.exports = class extends Chainable { | |||
return this; | |||
} | |||
|
|||
when(condition, trueBrancher = Function.prototype, falseBrancher = Function.prototype) { | |||
when(condition, whenTruthy = Function.prototype, whenFalsy = Function.prototype) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be in a separate cleanup commit in the PR :-)
@@ -53,8 +74,23 @@ module.exports = class extends Chainable { | |||
return this; | |||
} | |||
|
|||
merge(obj) { | |||
Object.keys(obj).forEach(key => this.set(key, obj[key])); | |||
merge(obj, omit = []) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and the other merge/omit parts could be a separate commit in the PR from the before/after parts :-)
src/Plugin.js
Outdated
@@ -28,12 +28,12 @@ module.exports = class extends ChainedMap { | |||
this.set('args', obj.args); | |||
} | |||
|
|||
return this; | |||
return super.merge(obj, [...omit, 'args', 'plugin']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing semicolon.
I wonder if we should add some linting to this repo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I've put it off for a while. I can do that in another PR, although it would be easier to either use Neutrino (seems circular) or move this repo into the monorepo.
test/Rule.js
Outdated
] | ||
}); | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a test for the "before and after aren't allowed at the same time" handling?
I think we also need some tests for all of the merge omit functionality?
6c7ae12
to
a9f8f37
Compare
OK, I think I got everything addressed. Thank you for the in-depth review! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Thank you for adding the extra tests :-)
README.md
Outdated
@@ -201,8 +201,11 @@ entries() | |||
```js | |||
// Provide an object which maps its properties and values | |||
// into the backing Map as keys and values. | |||
// You can also provide an array to the second argument |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/an array to the second argument/an array as the second argument/ maybe? Up to you :-)
README.md
Outdated
#### Config resolve plugins: ordering after | ||
|
||
Specify that the current `plugin` context should operate after another named `plugin`. | ||
You cannot use `.before()` and `.after()` on the same resolve plugin. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/cannot use/cannot use both/
src/Rule.js
Outdated
if (!omit.includes('oneOf') && 'oneOf' in obj) { | ||
Object | ||
.keys(obj.oneOf) | ||
.forEach(name => this.oneOf(name).merge(obj.oneOf[name])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing semicolon
README.md
Outdated
@@ -194,6 +193,8 @@ values() | |||
// where the key is the object property, and the value | |||
// corresponding to the key. Will return `undefined` if the backing | |||
// Map is empty. | |||
// This will order properties by their name if the value is also |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/also// ? Though happy for you to pick
README.md
Outdated
|
||
// Example | ||
|
||
config.resolve.plugin('beta') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The non-resolve examples and also the config.resolve "after" example below, put the .plugin()
on a new line, so I think this should be too?
src/Orderable.js
Outdated
module.exports = (Class) => class extends Class { | ||
before(name) { | ||
if (this.__after) { | ||
throw new Error(`Unable to set .before(${JSON.stringify(name)}) with existing value for after`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the with existing value for after
part need quotes or something around the "after", to make it clearer? (Or else .after()
?)
(And same for below)
a9f8f37
to
b0040bf
Compare
Accepted all your requests. |
🎉 |
No description provided.