Skip to content
This repository has been archived by the owner on Feb 18, 2024. It is now read-only.

Feature: allow specifying to use before or after other use #42

Merged
merged 3 commits into from
Oct 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 97 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ config
.entry('index')
.add('src/index.js')
.end()

// Modify output settings
.output
.path('dist')
Expand Down Expand Up @@ -194,25 +193,30 @@ 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
// a ChainedMap that used .before() or .after().
// returns: Object, undefined if empty
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 as the second argument
// for property names to omit from being merged.
// obj: Object
merge(obj)
// omit: Optional Array
merge(obj, omit)
```

```js
// Conditionally execute a function to continue configuration
// condition: Boolean
// truthyHandler: Function -> ChainedMap
// whenTruthy: Function -> ChainedMap
// invoked when condition is truthy, given a single argument of the ChainedMap instance
// falsyHandler: Function -> ChainedMap
// whenFalsy: Optional Function -> ChainedMap
// invoked when condition is falsy, given a single argument of the ChainedMap instance
when(condition, truthyHandler, falsyHandler)
when(condition, whenTruthy, whenFalsy)
```

## ChainedSet
Expand Down Expand Up @@ -269,11 +273,11 @@ merge(arr)
```js
// Conditionally execute a function to continue configuration
// condition: Boolean
// truthyHandler: Function -> ChainedSet
// whenTruthy: Function -> ChainedSet
// invoked when condition is truthy, given a single argument of the ChainedSet instance
// falsyHandler: Function -> ChainedSet
// whenFalsy: Optional Function -> ChainedSet
// invoked when condition is falsy, given a single argument of the ChainedSet instance
when(condition, truthyHandler, falsyHandler)
when(condition, whenTruthy, whenFalsy)
```

## Shorthand methods
Expand Down Expand Up @@ -353,7 +357,7 @@ config

config
.entry(name)
.clear()
.clear()

// Using low-level config.entryPoints:

Expand Down Expand Up @@ -608,6 +612,48 @@ config
config.plugins.delete(name)
```

#### Config plugins: ordering before

Specify that the current `plugin` context should operate before another named `plugin`.
You cannot use both `.before()` and `.after()` on the same plugin.

```js
config
.plugin(name)
.before(otherName)

// Example

config
.plugin('html-template')
.use(HtmlWebpackTemplate)
Copy link
Member

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?

.end()
.plugin('script-ext')
.use(ScriptExtWebpackPlugin)
.before('html-template');
```

#### Config plugins: ordering after

Specify that the current `plugin` context should operate after another named `plugin`.
You cannot use both `.before()` and `.after()` on the same plugin.

```js
config
.plugin(name)
.after(otherName)

// Example

config
.plugin('html-template')
.after('script-ext')
.use(HtmlWebpackTemplate)
.end()
.plugin('script-ext')
.use(ScriptExtWebpackPlugin);
```

#### Config resolve plugins

```js
Expand Down Expand Up @@ -647,6 +693,48 @@ config.resolve
config.resolve.plugins.delete(name)
```

#### Config resolve plugins: ordering before

Specify that the current `plugin` context should operate before another named `plugin`.
You cannot use both `.before()` and `.after()` on the same resolve plugin.

```js
config.resolve
.plugin(name)
.before(otherName)

// Example

config.resolve
.plugin('beta')
.use(BetaWebpackPlugin)
.end()
.plugin('alpha')
.use(AlphaWebpackPlugin)
.before('beta');
```

#### Config resolve plugins: ordering after

Specify that the current `plugin` context should operate after another named `plugin`.
You cannot use both `.before()` and `.after()` on the same resolve plugin.

```js
config.resolve
.plugin(name)
.after(otherName)

// Example

config.resolve
.plugin('beta')
.after('alpha')
.use(BetaWebpackTemplate)
.end()
.plugin('alpha')
.use(AlphaWebpackPlugin);
```

#### Config node

```js
Expand Down
65 changes: 51 additions & 14 deletions src/ChainedMap.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const merge = require('deepmerge');
const Chainable = require('./Chainable');

module.exports = class extends Chainable {
Expand All @@ -11,6 +12,7 @@ module.exports = class extends Chainable {
methods.map(method => {
this[method] = value => this.set(method, value);
});
return this;
}

clear() {
Expand All @@ -23,21 +25,41 @@ module.exports = class extends Chainable {
return this;
}

entries() {
const entries = [...this.store];

if (!entries.length) {
return;
}

return entries.reduce((acc, [key, value]) => {
order() {
const entries = [...this.store].reduce((acc, [key, value]) => {
acc[key] = value;
return acc;
}, {});
const names = Object.keys(entries);
const order = [...names];

names.forEach(name => {
const { __before, __after } = entries[name];

if (__before && order.includes(__before)) {
order.splice(order.indexOf(name), 1);
order.splice(order.indexOf(__before), 0, name);
} else if (__after && order.includes(__after)) {
order.splice(order.indexOf(name), 1);
order.splice(order.indexOf(__after) + 1, 0, name);
}
});

return { entries, order };
}

entries() {
const { entries, order } = this.order();

if (order.length) {
return entries;
}
}

values() {
return [...this.store.values()];
const { entries, order } = this.order();

return order.map(name => entries[name]);
}

get(key) {
Expand All @@ -53,8 +75,23 @@ module.exports = class extends Chainable {
return this;
}

merge(obj) {
Object.keys(obj).forEach(key => this.set(key, obj[key]));
merge(obj, omit = []) {
Copy link
Member

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 :-)

Object
.keys(obj)
.forEach(key => {
if (omit.includes(key)) {
return;
}

const value = obj[key];

if ((!Array.isArray(value) && typeof value !== 'object') || value === null || !this.has(key)) {
this.set(key, value);
} else {
this.set(key, merge(this.get(key), value));
}
});

return this;
}

Expand Down Expand Up @@ -82,11 +119,11 @@ module.exports = class extends Chainable {
}, {});
}

when(condition, trueBrancher = Function.prototype, falseBrancher = Function.prototype) {
when(condition, whenTruthy = Function.prototype, whenFalsy = Function.prototype) {
if (condition) {
trueBrancher(this);
whenTruthy(this);
} else {
falseBrancher(this);
whenFalsy(this);
}

return this;
Expand Down
6 changes: 3 additions & 3 deletions src/ChainedSet.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Copy link
Member

@edmorley edmorley Oct 5, 2017

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 :-)

if (condition) {
trueBrancher(this);
whenTruthy(this);
} else {
falseBrancher(this);
whenFalsy(this);
}

return this;
Expand Down
58 changes: 26 additions & 32 deletions src/Config.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,41 +74,35 @@ module.exports = class extends ChainedMap {
}));
}

merge(obj = {}) {
Object
.keys(obj)
.forEach(key => {
const value = obj[key];
merge(obj = {}, omit = []) {
const omissions = [
'node',
'output',
'resolve',
'resolveLoader',
'devServer',
'performance',
'module'
];

switch (key) {
case 'node':
case 'output':
case 'resolve':
case 'resolveLoader':
case 'devServer':
case 'performance':
case 'module': {
return this[key].merge(value);
}

case 'entry': {
return Object
.keys(value)
.forEach(name => this.entry(name).merge(value[name]));
}
if (!omit.includes('entry') && 'entry' in obj) {
Object
.keys(obj.entry)
.forEach(name => this.entry(name).merge(obj.entry[name]));
}

case 'plugin': {
return Object
.keys(value)
.forEach(name => this.plugin(name).merge(value[name]));
}
if (!omit.includes('plugin') && 'plugin' in obj) {
Object
.keys(obj.plugin)
.forEach(name => this.plugin(name).merge(obj.plugin[name]));
}

default: {
this.set(key, value);
}
}
});
omissions.forEach(key => {
if (!omit.includes(key) && key in obj) {
this[key].merge(obj[key]);
}
});

return this;
return super.merge(obj, [...omit, ...omissions, 'entry', 'plugin']);
}
};
26 changes: 5 additions & 21 deletions src/DevServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,27 +54,11 @@ module.exports = class extends ChainedMap {
}, this.entries() || {}));
}

merge(obj) {
Object
.keys(obj)
.forEach(key => {
const value = obj[key];
merge(obj, omit = []) {
if (!omit.includes('allowedHosts') && 'allowedHosts' in obj) {
this.allowedHosts.merge(obj.allowedHosts);
}

switch (key) {
case 'allowedHosts': {
return this[key].merge(value);
}

default: {
if (this.has(key)) {
this.set(key, merge(this.get(key), value));
} else {
this.set(key, value);
}
}
}
});

return this;
return super.merge(obj, ['allowedHosts']);
}
};
Loading