Skip to content

Commit c176d7d

Browse files
authoredMay 12, 2020
feat: concurrency option (#466)
1 parent e5e410a commit c176d7d

File tree

6 files changed

+83
-74
lines changed

6 files changed

+83
-74
lines changed
 

‎README.md

+10-4
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ module.exports = {
6565
{ from: 'other', to: 'public' },
6666
],
6767
options: {
68-
ignore: ['*.bin'],
68+
concurrency: 100,
6969
},
7070
}),
7171
],
@@ -562,9 +562,15 @@ module.exports = {
562562
};
563563
```
564564

565-
#### `ignore`
565+
### Options
566566

567-
Array of globs to ignore (applied to `from`).
567+
| Name | Type | Default | Description |
568+
| :---------------------------: | :--------: | :-----: | :----------------------------------------------- |
569+
| [`concurrency`](#concurrency) | `{Number}` | `100` | Limits the number of simultaneous requests to fs |
570+
571+
#### `concurrency`
572+
573+
limits the number of simultaneous requests to fs
568574

569575
**webpack.config.js**
570576

@@ -573,7 +579,7 @@ module.exports = {
573579
plugins: [
574580
new CopyPlugin({
575581
patterns: [...patterns],
576-
options: { ignore: ['*.js', '*.css'] },
582+
options: { concurrency: 50 },
577583
}),
578584
],
579585
};

‎src/index.js

+27-24
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import validateOptions from 'schema-utils';
2+
import pLimit from 'p-limit';
23

34
import schema from './options.json';
45
import preProcessPattern from './preProcessPattern';
@@ -18,6 +19,7 @@ class CopyPlugin {
1819

1920
apply(compiler) {
2021
const plugin = { name: 'CopyPlugin' };
22+
const limit = pLimit(this.options.concurrency || 100);
2123

2224
compiler.hooks.compilation.tap(plugin, (compilation) => {
2325
const logger = compilation.getLogger('copy-webpack-plugin');
@@ -33,38 +35,39 @@ class CopyPlugin {
3335
compilation,
3436
inputFileSystem: compiler.inputFileSystem,
3537
output: compiler.options.output.path,
36-
concurrency: this.options.concurrency,
3738
};
3839

3940
try {
4041
await Promise.all(
41-
this.patterns.map(async (pattern) => {
42-
const patternAfterPreProcess = await preProcessPattern(
43-
globalRef,
44-
pattern
45-
);
42+
this.patterns.map((pattern) =>
43+
limit(async () => {
44+
const patternAfterPreProcess = await preProcessPattern(
45+
globalRef,
46+
pattern
47+
);
4648

47-
const files = await processPattern(
48-
globalRef,
49-
patternAfterPreProcess
50-
);
49+
const files = await processPattern(
50+
globalRef,
51+
patternAfterPreProcess
52+
);
5153

52-
if (!files) {
53-
return Promise.resolve();
54-
}
54+
if (!files) {
55+
return Promise.resolve();
56+
}
5557

56-
return Promise.all(
57-
files
58-
.filter(Boolean)
59-
.map((file) =>
60-
postProcessPattern(
61-
globalRef,
62-
patternAfterPreProcess,
63-
file
64-
)
58+
return Promise.all(
59+
files.filter(Boolean).map((file) =>
60+
limit(() => {
61+
return postProcessPattern(
62+
globalRef,
63+
patternAfterPreProcess,
64+
file
65+
);
66+
})
6567
)
66-
);
67-
})
68+
);
69+
})
70+
)
6871
);
6972

7073
logger.debug('end to adding additionalAssets');

‎src/options.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,11 @@
7676
"options": {
7777
"type": "object",
7878
"additionalProperties": false,
79-
"properties": {}
79+
"properties": {
80+
"concurrency": {
81+
"type": "number"
82+
}
83+
}
8084
}
8185
}
8286
}

‎src/processPattern.js

+33-42
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
import path from 'path';
22

33
import globby from 'globby';
4-
import pLimit from 'p-limit';
54

65
import createPatternGlob from './utils/createPatternGlob';
76

87
/* eslint-disable no-param-reassign */
98

109
export default async function processPattern(globalRef, pattern) {
11-
const { logger, output, concurrency, compilation } = globalRef;
10+
const { logger, output, compilation } = globalRef;
1211
createPatternGlob(pattern, globalRef);
1312

14-
const limit = pLimit(concurrency || 100);
15-
1613
logger.log(
1714
`begin globbing '${pattern.glob}' with a context of '${pattern.context}'`
1815
);
@@ -38,42 +35,36 @@ export default async function processPattern(globalRef, pattern) {
3835
return Promise.resolve();
3936
}
4037

41-
return Promise.all(
42-
paths.map((from) =>
43-
limit(() => {
44-
const file = {
45-
force: pattern.force,
46-
absoluteFrom: path.resolve(pattern.context, from),
47-
};
48-
49-
file.relativeFrom = path.relative(pattern.context, file.absoluteFrom);
50-
51-
if (pattern.flatten) {
52-
file.relativeFrom = path.basename(file.relativeFrom);
53-
}
54-
55-
logger.debug(`found ${from}`);
56-
57-
// Change the to path to be relative for webpack
58-
if (pattern.toType === 'dir') {
59-
file.webpackTo = path.join(pattern.to, file.relativeFrom);
60-
} else if (pattern.toType === 'file') {
61-
file.webpackTo = pattern.to || file.relativeFrom;
62-
} else if (pattern.toType === 'template') {
63-
file.webpackTo = pattern.to;
64-
file.webpackToRegExp = pattern.test;
65-
}
66-
67-
if (path.isAbsolute(file.webpackTo)) {
68-
file.webpackTo = path.relative(output, file.webpackTo);
69-
}
70-
71-
logger.log(
72-
`determined that '${from}' should write to '${file.webpackTo}'`
73-
);
74-
75-
return file;
76-
})
77-
)
78-
);
38+
return paths.map((from) => {
39+
const file = {
40+
force: pattern.force,
41+
absoluteFrom: path.resolve(pattern.context, from),
42+
};
43+
44+
file.relativeFrom = path.relative(pattern.context, file.absoluteFrom);
45+
46+
if (pattern.flatten) {
47+
file.relativeFrom = path.basename(file.relativeFrom);
48+
}
49+
50+
logger.debug(`found ${from}`);
51+
52+
// Change the to path to be relative for webpack
53+
if (pattern.toType === 'dir') {
54+
file.webpackTo = path.join(pattern.to, file.relativeFrom);
55+
} else if (pattern.toType === 'file') {
56+
file.webpackTo = pattern.to || file.relativeFrom;
57+
} else if (pattern.toType === 'template') {
58+
file.webpackTo = pattern.to;
59+
file.webpackToRegExp = pattern.test;
60+
}
61+
62+
if (path.isAbsolute(file.webpackTo)) {
63+
file.webpackTo = path.relative(output, file.webpackTo);
64+
}
65+
66+
logger.log(`determined that '${from}' should write to '${file.webpackTo}'`);
67+
68+
return file;
69+
});
7970
}

‎test/__snapshots__/validate-options.test.js.snap

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`validate options should throw an error on the "options" option with "{"concurrency":true}" value 1`] = `
4+
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
5+
- options.options.concurrency should be a number."
6+
`;
7+
38
exports[`validate options should throw an error on the "options" option with "{"unknown":true}" value 1`] = `
49
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
510
- options.options has an unknown property 'unknown'. These properties are valid:
6-
object {}"
11+
object { concurrency? }"
712
`;
813
914
exports[`validate options should throw an error on the "patterns" option with "" value 1`] = `

‎test/validate-options.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,8 @@ describe('validate options', () => {
203203
],
204204
},
205205
options: {
206-
success: [{}],
207-
failure: [{ unknown: true }],
206+
success: [{ concurrency: 50 }],
207+
failure: [{ unknown: true }, { concurrency: true }],
208208
},
209209
unknown: {
210210
success: [],

0 commit comments

Comments
 (0)
Please sign in to comment.