1 | <div align="center">
|
2 | <a href="https://github.com/webpack/webpack">
|
3 | <img width="200" height="200"
|
4 | src="https://webpack.js.org/assets/icon-square-big.svg">
|
5 | </a>
|
6 | </div>
|
7 |
|
8 | [![npm][npm]][npm-url]
|
9 | [![node][node]][node-url]
|
10 | [![deps][deps]][deps-url]
|
11 | [![tests][tests]][tests-url]
|
12 | [![cover][cover]][cover-url]
|
13 | [![chat][chat]][chat-url]
|
14 | [![size][size]][size-url]
|
15 |
|
16 | # copy-webpack-plugin
|
17 |
|
18 | Copies individual files or entire directories, which already exist, to the build directory.
|
19 |
|
20 | ## Getting Started
|
21 |
|
22 | To begin, you'll need to install `copy-webpack-plugin`:
|
23 |
|
24 | ```console
|
25 | npm install copy-webpack-plugin --save-dev
|
26 | ```
|
27 |
|
28 | or
|
29 |
|
30 | ```console
|
31 | yarn add -D copy-webpack-plugin
|
32 | ```
|
33 |
|
34 | or
|
35 |
|
36 | ```console
|
37 | pnpm add -D copy-webpack-plugin
|
38 | ```
|
39 |
|
40 | Then add the plugin to your `webpack` config. For example:
|
41 |
|
42 | **webpack.config.js**
|
43 |
|
44 | ```js
|
45 | const CopyPlugin = require("copy-webpack-plugin");
|
46 |
|
47 | module.exports = {
|
48 | plugins: [
|
49 | new CopyPlugin({
|
50 | patterns: [
|
51 | { from: "source", to: "dest" },
|
52 | { from: "other", to: "public" },
|
53 | ],
|
54 | }),
|
55 | ],
|
56 | };
|
57 | ```
|
58 |
|
59 | > ℹ️ `copy-webpack-plugin` is not designed to copy files generated from the build process; rather, it is to copy files that already exist in the source tree, as part of the build process.
|
60 |
|
61 | > ℹ️ If you want `webpack-dev-server` to write files to the output directory during development, you can force it with the [`writeToDisk`](https://github.com/webpack/webpack-dev-middleware#writetodisk) option or the [`write-file-webpack-plugin`](https://github.com/gajus/write-file-webpack-plugin).
|
62 |
|
63 | > ℹ️ You can get the original source filename from [Asset Objects](https://webpack.js.org/api/stats/#asset-objects).
|
64 |
|
65 | ## Options
|
66 |
|
67 | - **[`patterns`](#patterns)**
|
68 | - **[`options`](#options-1)**
|
69 |
|
70 | The plugin's signature:
|
71 |
|
72 | **webpack.config.js**
|
73 |
|
74 | ```js
|
75 | const CopyPlugin = require("copy-webpack-plugin");
|
76 |
|
77 | module.exports = {
|
78 | plugins: [
|
79 | new CopyPlugin({
|
80 | patterns: [
|
81 | { from: "source", to: "dest" },
|
82 | "path/to/source", // absolute or relative, files/directories/globs - see below for examples
|
83 | ],
|
84 | options: {
|
85 | concurrency: 100,
|
86 | },
|
87 | }),
|
88 | ],
|
89 | };
|
90 | ```
|
91 |
|
92 | ### `Patterns`
|
93 |
|
94 | - [`from`](#from)
|
95 | - [`to`](#to)
|
96 | - [`context`](#context)
|
97 | - [`globOptions`](#globoptions)
|
98 | - [`filter`](#filter)
|
99 | - [`toType`](#totype)
|
100 | - [`force`](#force)
|
101 | - [`priority`](#priority)
|
102 | - [`transform`](#transform)
|
103 | - [`transformAll`](#transformAll)
|
104 | - [`noErrorOnMissing`](#noerroronmissing)
|
105 | - [`info`](#info)
|
106 |
|
107 | #### `from`
|
108 |
|
109 | Type:
|
110 |
|
111 | ```ts
|
112 | type from = string;
|
113 | ```
|
114 |
|
115 | Default: `undefined`
|
116 |
|
117 | Glob or path from where we copy files.
|
118 | Globs accept [fast-glob pattern-syntax](https://github.com/mrmlnc/fast-glob#pattern-syntax).
|
119 | Glob can only be a `string`.
|
120 |
|
121 | > ⚠️ Don't use directly `\\` in `from` option if it is a `glob` (i.e `path\to\file.ext`) option because on UNIX the backslash is a valid character inside a path component, i.e., it's not a separator.
|
122 | > On Windows, the forward slash and the backward slash are both separators.
|
123 | > Instead please use `/`.
|
124 |
|
125 | **webpack.config.js**
|
126 |
|
127 | ```js
|
128 | module.exports = {
|
129 | plugins: [
|
130 | new CopyPlugin({
|
131 | patterns: [
|
132 | "relative/path/to/file.ext",
|
133 | "relative/path/to/dir",
|
134 | path.resolve(__dirname, "src", "file.ext"),
|
135 | path.resolve(__dirname, "src", "dir"),
|
136 | "**/*",
|
137 | {
|
138 | from: "**/*",
|
139 | },
|
140 | // If absolute path is a `glob` we replace backslashes with forward slashes, because only forward slashes can be used in the `glob`
|
141 | path.posix.join(
|
142 | path.resolve(__dirname, "src").replace(/\\/g, "/"),
|
143 | "*.txt"
|
144 | ),
|
145 | ],
|
146 | }),
|
147 | ],
|
148 | };
|
149 | ```
|
150 |
|
151 | ##### `For windows`
|
152 |
|
153 | If you define `from` as absolute file path or absolute folder path on `Windows`, you can use windows path segment (`\\`)
|
154 |
|
155 | ```js
|
156 | module.exports = {
|
157 | plugins: [
|
158 | new CopyPlugin({
|
159 | patterns: [
|
160 | {
|
161 | from: path.resolve(__dirname, "file.txt"),
|
162 | },
|
163 | ],
|
164 | }),
|
165 | ],
|
166 | };
|
167 | ```
|
168 |
|
169 | But you should always use forward-slashes in `glob` expressions
|
170 | See [fast-glob manual](https://github.com/mrmlnc/fast-glob#how-to-write-patterns-on-windows).
|
171 |
|
172 | ```js
|
173 | module.exports = {
|
174 | plugins: [
|
175 | new CopyPlugin({
|
176 | patterns: [
|
177 | {
|
178 | // If absolute path is a `glob` we replace backslashes with forward slashes, because only forward slashes can be used in the `glob`
|
179 | from: path.posix.join(
|
180 | path.resolve(__dirname, "fixtures").replace(/\\/g, "/"),
|
181 | "*.txt"
|
182 | ),
|
183 | },
|
184 | ],
|
185 | }),
|
186 | ],
|
187 | };
|
188 | ```
|
189 |
|
190 | The `context` behaves differently depending on what the `from` is (`glob`, `file` or `dir`).
|
191 | More [`examples`](#examples)
|
192 |
|
193 | #### `to`
|
194 |
|
195 | Type:
|
196 |
|
197 | ```ts
|
198 | type to =
|
199 | | string
|
200 | | ((pathData: { context: string; absoluteFilename?: string }) => string);
|
201 | ```
|
202 |
|
203 | Default: `compiler.options.output`
|
204 |
|
205 | ##### `string`
|
206 |
|
207 | Output path.
|
208 |
|
209 | > ⚠️ Don't use directly `\\` in `to` (i.e `path\to\dest`) option because on UNIX the backslash is a valid character inside a path component, i.e., it's not a separator.
|
210 | > On Windows, the forward slash and the backward slash are both separators.
|
211 | > Instead please use `/` or `path` methods.
|
212 |
|
213 | **webpack.config.js**
|
214 |
|
215 | ```js
|
216 | module.exports = {
|
217 | plugins: [
|
218 | new CopyPlugin({
|
219 | patterns: [
|
220 | {
|
221 | from: "**/*",
|
222 | to: "relative/path/to/dest/",
|
223 | },
|
224 | {
|
225 | from: "**/*",
|
226 | to: "/absolute/path/to/dest/",
|
227 | },
|
228 | {
|
229 | from: "**/*",
|
230 | to: "[path][name].[contenthash][ext]",
|
231 | },
|
232 | ],
|
233 | }),
|
234 | ],
|
235 | };
|
236 | ```
|
237 |
|
238 | ##### `function`
|
239 |
|
240 | Allows to modify the writing path.
|
241 |
|
242 | > ⚠️ Don't return directly `\\` in `to` (i.e `path\to\newFile`) option because on UNIX the backslash is a valid character inside a path component, i.e., it's not a separator.
|
243 | > On Windows, the forward slash and the backward slash are both separators.
|
244 | > Instead please use `/` or `path` methods.
|
245 |
|
246 | **webpack.config.js**
|
247 |
|
248 | ```js
|
249 | module.exports = {
|
250 | plugins: [
|
251 | new CopyPlugin({
|
252 | patterns: [
|
253 | {
|
254 | from: "src/*.png",
|
255 | to({ context, absoluteFilename }) {
|
256 | return "dest/newPath/[name][ext]";
|
257 | },
|
258 | },
|
259 | ],
|
260 | }),
|
261 | ],
|
262 | };
|
263 | ```
|
264 |
|
265 | **webpack.config.js**
|
266 |
|
267 | ```js
|
268 | module.exports = {
|
269 | plugins: [
|
270 | new CopyPlugin({
|
271 | patterns: [
|
272 | {
|
273 | from: "src/*.png",
|
274 | to({ context, absoluteFilename }) {
|
275 | return Promise.resolve("dest/newPath/[name][ext]");
|
276 | },
|
277 | },
|
278 | ],
|
279 | }),
|
280 | ],
|
281 | };
|
282 | ```
|
283 |
|
284 | #### `context`
|
285 |
|
286 | Type:
|
287 |
|
288 | ```ts
|
289 | type context = string;
|
290 | ```
|
291 |
|
292 | Default: `options.context|compiler.options.context`
|
293 |
|
294 | A path that determines how to interpret the `from` path.
|
295 |
|
296 | > ⚠️ Don't use directly `\\` in `context` (i.e `path\to\context`) option because on UNIX the backslash is a valid character inside a path component, i.e., it's not a separator.
|
297 | > On Windows, the forward slash and the backward slash are both separators.
|
298 | > Instead please use `/` or `path` methods.
|
299 |
|
300 | **webpack.config.js**
|
301 |
|
302 | ```js
|
303 | module.exports = {
|
304 | plugins: [
|
305 | new CopyPlugin({
|
306 | patterns: [
|
307 | {
|
308 | from: "src/*.txt",
|
309 | to: "dest/",
|
310 | context: "app/",
|
311 | },
|
312 | ],
|
313 | }),
|
314 | ],
|
315 | };
|
316 | ```
|
317 |
|
318 | The `context` option can be an absolute or relative path. If `context` is a relative, then it is converted to absolute based to `compiler.options.context`
|
319 |
|
320 | To determine the structure from which the found resources will be copied to the destination folder, the `context` option is used.
|
321 |
|
322 | If `from` is a file, then `context` is equal to the directory in which this file is located. Accordingly, the result will be only the file name.
|
323 |
|
324 | If `from` is a directory, then `context` is the same as `from` and is equal to the directory itself. In this case, the result will be a hierarchical structure of the found folders and files relative to the specified directory.
|
325 |
|
326 | If `from` is a glob, then regardless of the `context` option, the result will be the structure specified in the `from` option
|
327 |
|
328 | More [`examples`](#examples)
|
329 |
|
330 | #### `globOptions`
|
331 |
|
332 | Type:
|
333 |
|
334 | ```ts
|
335 | type globOptions = import("globby").Options;
|
336 | ```
|
337 |
|
338 | Default: `undefined`
|
339 |
|
340 | Allows to configure the glob pattern matching library used by the plugin. [See the list of supported options][glob-options]
|
341 | To exclude files from the selection, you should use [globOptions.ignore option](https://github.com/mrmlnc/fast-glob#ignore)
|
342 |
|
343 | **webpack.config.js**
|
344 |
|
345 | ```js
|
346 | module.exports = {
|
347 | plugins: [
|
348 | new CopyPlugin({
|
349 | patterns: [
|
350 | {
|
351 | from: "public/**/*",
|
352 | globOptions: {
|
353 | dot: true,
|
354 | gitignore: true,
|
355 | ignore: ["**/file.*", "**/ignored-directory/**"],
|
356 | },
|
357 | },
|
358 | ],
|
359 | }),
|
360 | ],
|
361 | };
|
362 | ```
|
363 |
|
364 | #### `filter`
|
365 |
|
366 | Type:
|
367 |
|
368 | ```ts
|
369 | type filter = (filepath: string) => boolean;
|
370 | ```
|
371 |
|
372 | Default: `undefined`
|
373 |
|
374 | > ℹ️ To ignore files by path please use the [`globOptions.ignore`](#globoptions) option.
|
375 |
|
376 | **webpack.config.js**
|
377 |
|
378 | ```js
|
379 | const fs = require("fs").promise;
|
380 |
|
381 | module.exports = {
|
382 | plugins: [
|
383 | new CopyPlugin({
|
384 | patterns: [
|
385 | {
|
386 | from: "public/**/*",
|
387 | filter: async (resourcePath) => {
|
388 | const data = await fs.promises.readFile(resourcePath);
|
389 | const content = data.toString();
|
390 |
|
391 | if (content === "my-custom-content") {
|
392 | return false;
|
393 | }
|
394 |
|
395 | return true;
|
396 | },
|
397 | },
|
398 | ],
|
399 | }),
|
400 | ],
|
401 | };
|
402 | ```
|
403 |
|
404 | #### `toType`
|
405 |
|
406 | Type:
|
407 |
|
408 | ```ts
|
409 | type toType = "dir" | "file" | "template";
|
410 | ```
|
411 |
|
412 | Default: `undefined`
|
413 |
|
414 | Determinate what is `to` option - directory, file or template.
|
415 | Sometimes it is hard to say what is `to`, example `path/to/dir-with.ext`.
|
416 | If you want to copy files in directory you need use `dir` option.
|
417 | We try to automatically determine the `type` so you most likely do not need this option.
|
418 |
|
419 | | Name | Type | Default | Description |
|
420 | | :---------------------------: | :------: | :---------: | :--------------------------------------------------------------------------------------------------- |
|
421 | | **[`'dir'`](#dir)** | `string` | `undefined` | If `to` has no extension or ends on `'/'` |
|
422 | | **[`'file'`](#file)** | `string` | `undefined` | If `to` is not a directory and is not a template |
|
423 | | **[`'template'`](#template)** | `string` | `undefined` | If `to` contains [a template pattern](https://webpack.js.org/configuration/output/#template-strings) |
|
424 |
|
425 | ##### `'dir'`
|
426 |
|
427 | **webpack.config.js**
|
428 |
|
429 | ```js
|
430 | module.exports = {
|
431 | plugins: [
|
432 | new CopyPlugin({
|
433 | patterns: [
|
434 | {
|
435 | from: "path/to/file.txt",
|
436 | to: "directory/with/extension.ext",
|
437 | toType: "dir",
|
438 | },
|
439 | ],
|
440 | }),
|
441 | ],
|
442 | };
|
443 | ```
|
444 |
|
445 | ##### `'file'`
|
446 |
|
447 | **webpack.config.js**
|
448 |
|
449 | ```js
|
450 | module.exports = {
|
451 | plugins: [
|
452 | new CopyPlugin({
|
453 | patterns: [
|
454 | {
|
455 | from: "path/to/file.txt",
|
456 | to: "file/without/extension",
|
457 | toType: "file",
|
458 | },
|
459 | ],
|
460 | }),
|
461 | ],
|
462 | };
|
463 | ```
|
464 |
|
465 | ##### `'template'`
|
466 |
|
467 | **webpack.config.js**
|
468 |
|
469 | ```js
|
470 | module.exports = {
|
471 | plugins: [
|
472 | new CopyPlugin({
|
473 | patterns: [
|
474 | {
|
475 | from: "src/",
|
476 | to: "dest/[name].[contenthash][ext]",
|
477 | toType: "template",
|
478 | },
|
479 | ],
|
480 | }),
|
481 | ],
|
482 | };
|
483 | ```
|
484 |
|
485 | #### `force`
|
486 |
|
487 | Type:
|
488 |
|
489 | ```ts
|
490 | type force = boolean;
|
491 | ```
|
492 |
|
493 | Default: `false`
|
494 |
|
495 | Overwrites files already in `compilation.assets` (usually added by other plugins/loaders).
|
496 |
|
497 | **webpack.config.js**
|
498 |
|
499 | ```js
|
500 | module.exports = {
|
501 | plugins: [
|
502 | new CopyPlugin({
|
503 | patterns: [
|
504 | {
|
505 | from: "src/**/*",
|
506 | to: "dest/",
|
507 | force: true,
|
508 | },
|
509 | ],
|
510 | }),
|
511 | ],
|
512 | };
|
513 | ```
|
514 |
|
515 | #### `priority`
|
516 |
|
517 | Type:
|
518 |
|
519 | ```ts
|
520 | type priority = number;
|
521 | ```
|
522 |
|
523 | Default: `0`
|
524 |
|
525 | Allows to specify the priority of copying files with the same destination name.
|
526 | Files for patterns with higher priority will be copied later.
|
527 | To overwrite files, the [`force`](#force) option must be enabled.
|
528 |
|
529 | **webpack.config.js**
|
530 |
|
531 | ```js
|
532 | module.exports = {
|
533 | plugins: [
|
534 | new CopyPlugin({
|
535 | patterns: [
|
536 | // Copied second and will overwrite "dir_2/file.txt"
|
537 | {
|
538 | from: "dir_1/file.txt",
|
539 | to: "newfile.txt",
|
540 | force: true,
|
541 | priority: 10,
|
542 | },
|
543 | // Copied first
|
544 | {
|
545 | from: "dir_2/file.txt",
|
546 | to: "newfile.txt",
|
547 | priority: 5,
|
548 | },
|
549 | ],
|
550 | }),
|
551 | ],
|
552 | };
|
553 | ```
|
554 |
|
555 | #### `transform`
|
556 |
|
557 | Type:
|
558 |
|
559 | ```ts
|
560 | type transform =
|
561 | | {
|
562 | transformer: (input: string, absoluteFilename: string) => string | Buffer;
|
563 | cache?: boolean | TransformerCacheObject | undefined;
|
564 | }
|
565 | | ((input: string, absoluteFilename: string) => string | Buffer);
|
566 | ```
|
567 |
|
568 | Default: `undefined`
|
569 |
|
570 | Allows to modify the file contents.
|
571 |
|
572 | ##### `function`
|
573 |
|
574 | **webpack.config.js**
|
575 |
|
576 | ```js
|
577 | module.exports = {
|
578 | plugins: [
|
579 | new CopyPlugin({
|
580 | patterns: [
|
581 | {
|
582 | from: "src/*.png",
|
583 | to: "dest/",
|
584 | // The `content` argument is a [`Buffer`](https://nodejs.org/api/buffer.html) object, it could be converted to a `String` to be processed using `content.toString()`
|
585 | // The `absoluteFrom` argument is a `String`, it is absolute path from where the file is being copied
|
586 | transform(content, absoluteFrom) {
|
587 | return optimize(content);
|
588 | },
|
589 | },
|
590 | ],
|
591 | }),
|
592 | ],
|
593 | };
|
594 | ```
|
595 |
|
596 | ##### `object`
|
597 |
|
598 | | Name | Default | Description |
|
599 | | :-------------------------------: | :---------: | :--------------------------------------------------------------------------------------------------------------- |
|
600 | | **[`transformer`](#transformer)** | `undefined` | Allows to modify the file contents. |
|
601 | | **[`cache`](#cache)** | `false` | Enable `transform` caching. You can use `transform: { cache: { key: 'my-cache-key' } }` to invalidate the cache. |
|
602 |
|
603 | ###### `transformer`
|
604 |
|
605 | Type:
|
606 |
|
607 | ```ts
|
608 | type transformer = (input: string, absoluteFilename: string) => string;
|
609 | ```
|
610 |
|
611 | Default: `undefined`
|
612 |
|
613 | **webpack.config.js**
|
614 |
|
615 | ```js
|
616 | module.exports = {
|
617 | plugins: [
|
618 | new CopyPlugin({
|
619 | patterns: [
|
620 | {
|
621 | from: "src/*.png",
|
622 | to: "dest/",
|
623 | // The `content` argument is a [`Buffer`](https://nodejs.org/api/buffer.html) object, it could be converted to a `String` to be processed using `content.toString()`
|
624 | // The `absoluteFrom` argument is a `String`, it is absolute path from where the file is being copied
|
625 | transform: {
|
626 | transformer(content, absoluteFrom) {
|
627 | return optimize(content);
|
628 | },
|
629 | },
|
630 | },
|
631 | ],
|
632 | }),
|
633 | ],
|
634 | };
|
635 | ```
|
636 |
|
637 | **webpack.config.js**
|
638 |
|
639 | ```js
|
640 | module.exports = {
|
641 | plugins: [
|
642 | new CopyPlugin({
|
643 | patterns: [
|
644 | {
|
645 | from: "src/*.png",
|
646 | to: "dest/",
|
647 | transform: {
|
648 | transformer(content, path) {
|
649 | return Promise.resolve(optimize(content));
|
650 | },
|
651 | },
|
652 | },
|
653 | ],
|
654 | }),
|
655 | ],
|
656 | };
|
657 | ```
|
658 |
|
659 | ###### `cache`
|
660 |
|
661 | Type:
|
662 |
|
663 | ```ts
|
664 | type cache =
|
665 | | boolean
|
666 | | {
|
667 | keys: {
|
668 | [key: string]: any;
|
669 | };
|
670 | }
|
671 | | {
|
672 | keys: (
|
673 | defaultCacheKeys: {
|
674 | [key: string]: any;
|
675 | },
|
676 | absoluteFilename: string
|
677 | ) => Promise<{
|
678 | [key: string]: any;
|
679 | }>;
|
680 | }
|
681 | | undefined;
|
682 | ```
|
683 |
|
684 | Default: `false`
|
685 |
|
686 | **webpack.config.js**
|
687 |
|
688 | Enable/disable and configure caching.
|
689 | Default path to cache directory: `node_modules/.cache/copy-webpack-plugin`.
|
690 |
|
691 | ###### `boolean`
|
692 |
|
693 | Enables/Disable `transform` caching.
|
694 |
|
695 | **webpack.config.js**
|
696 |
|
697 | ```js
|
698 | module.exports = {
|
699 | plugins: [
|
700 | new CopyPlugin({
|
701 | patterns: [
|
702 | {
|
703 | from: "src/*.png",
|
704 | to: "dest/",
|
705 | transform: {
|
706 | transformer(content, path) {
|
707 | return optimize(content);
|
708 | },
|
709 | cache: true,
|
710 | },
|
711 | },
|
712 | ],
|
713 | }),
|
714 | ],
|
715 | };
|
716 | ```
|
717 |
|
718 | ##### `object`
|
719 |
|
720 | Enables `transform` caching and setup cache directory and invalidation keys.
|
721 |
|
722 | **webpack.config.js**
|
723 |
|
724 | ```js
|
725 | module.exports = {
|
726 | plugins: [
|
727 | new CopyPlugin({
|
728 | patterns: [
|
729 | {
|
730 | from: "src/*.png",
|
731 | to: "dest/",
|
732 | transform: {
|
733 | transformer(content, path) {
|
734 | return optimize(content);
|
735 | },
|
736 | cache: {
|
737 | directory: path.resolve(__dirname, "cache-directory"),
|
738 | keys: {
|
739 | // May be useful for invalidating cache based on external values
|
740 | // For example, you can invalid cache based on `process.version` - { node: process.version }
|
741 | key: "value",
|
742 | },
|
743 | },
|
744 | },
|
745 | },
|
746 | ],
|
747 | }),
|
748 | ],
|
749 | };
|
750 | ```
|
751 |
|
752 | You can setup invalidation keys using a function.
|
753 |
|
754 | Simple function:
|
755 |
|
756 | **webpack.config.js**
|
757 |
|
758 | ```js
|
759 | module.exports = {
|
760 | plugins: [
|
761 | new CopyPlugin({
|
762 | patterns: [
|
763 | {
|
764 | from: "src/*.png",
|
765 | to: "dest/",
|
766 | transform: {
|
767 | transformer(content, path) {
|
768 | return optimize(content);
|
769 | },
|
770 | cache: {
|
771 | directory: path.resolve(__dirname, "cache-directory"),
|
772 | keys: (defaultCacheKeys, absoluteFrom) => {
|
773 | const keys = getCustomCacheInvalidationKeysSync();
|
774 |
|
775 | return {
|
776 | ...defaultCacheKeys,
|
777 | keys,
|
778 | };
|
779 | },
|
780 | },
|
781 | },
|
782 | },
|
783 | ],
|
784 | }),
|
785 | ],
|
786 | };
|
787 | ```
|
788 |
|
789 | Async function:
|
790 |
|
791 | **webpack.config.js**
|
792 |
|
793 | ```js
|
794 | module.exports = {
|
795 | plugins: [
|
796 | new CopyPlugin({
|
797 | patterns: [
|
798 | {
|
799 | from: "src/*.png",
|
800 | to: "dest/",
|
801 | transform: {
|
802 | transformer(content, path) {
|
803 | return optimize(content);
|
804 | },
|
805 | cache: {
|
806 | directory: path.resolve(__dirname, "cache-directory"),
|
807 | keys: async (defaultCacheKeys, absoluteFrom) => {
|
808 | const keys = await getCustomCacheInvalidationKeysAsync();
|
809 |
|
810 | return {
|
811 | ...defaultCacheKeys,
|
812 | keys,
|
813 | };
|
814 | },
|
815 | },
|
816 | },
|
817 | },
|
818 | ],
|
819 | }),
|
820 | ],
|
821 | };
|
822 | ```
|
823 |
|
824 | #### `transformAll`
|
825 |
|
826 | Type:
|
827 |
|
828 | ```ts
|
829 | type transformAll = (
|
830 | data: {
|
831 | data: Buffer;
|
832 | sourceFilename: string;
|
833 | absoluteFilename: string;
|
834 | }[]
|
835 | ) => any;
|
836 | ```
|
837 |
|
838 | Default: `undefined`
|
839 |
|
840 | Allows you to modify the contents of multiple files and save the result to one file.
|
841 |
|
842 | > ℹ️ The `to` option must be specified and point to a file. It is allowed to use only `[contenthash]` and `[fullhash]` template strings.
|
843 |
|
844 | **webpack.config.js**
|
845 |
|
846 | ```js
|
847 | module.exports = {
|
848 | plugins: [
|
849 | new CopyPlugin({
|
850 | patterns: [
|
851 | {
|
852 | from: "src/**/*.txt",
|
853 | to: "dest/file.txt",
|
854 | // The `assets` argument is an assets array for the pattern.from ("src/**/*.txt")
|
855 | transformAll(assets) {
|
856 | const result = assets.reduce((accumulator, asset) => {
|
857 | // The asset content can be obtained from `asset.source` using `source` method.
|
858 | // The asset content is a [`Buffer`](https://nodejs.org/api/buffer.html) object, it could be converted to a `String` to be processed using `content.toString()`
|
859 | const content = asset.data;
|
860 |
|
861 | accumulator = `${accumulator}${content}\n`;
|
862 | return accumulator;
|
863 | }, "");
|
864 |
|
865 | return result;
|
866 | },
|
867 | },
|
868 | ],
|
869 | }),
|
870 | ],
|
871 | };
|
872 | ```
|
873 |
|
874 | ### `noErrorOnMissing`
|
875 |
|
876 | Type:
|
877 |
|
878 | ```ts
|
879 | type noErrorOnMissing = boolean;
|
880 | ```
|
881 |
|
882 | Default: `false`
|
883 |
|
884 | Doesn't generate an error on missing file(s).
|
885 |
|
886 | ```js
|
887 | module.exports = {
|
888 | plugins: [
|
889 | new CopyPlugin({
|
890 | patterns: [
|
891 | {
|
892 | from: path.resolve(__dirname, "missing-file.txt"),
|
893 | noErrorOnMissing: true,
|
894 | },
|
895 | ],
|
896 | }),
|
897 | ],
|
898 | };
|
899 | ```
|
900 |
|
901 | #### `info`
|
902 |
|
903 | Type:
|
904 |
|
905 | ```ts
|
906 | type info =
|
907 | | Record<string, any>
|
908 | | ((item: {
|
909 | absoluteFilename: string;
|
910 | sourceFilename: string;
|
911 | filename: string;
|
912 | toType: ToType;
|
913 | }) => Record<string, any>);
|
914 | ```
|
915 |
|
916 | Default: `undefined`
|
917 |
|
918 | Allows to add assets info.
|
919 |
|
920 | **webpack.config.js**
|
921 |
|
922 | ```js
|
923 | module.exports = {
|
924 | plugins: [
|
925 | new CopyPlugin({
|
926 | patterns: [
|
927 | "relative/path/to/file.ext",
|
928 | {
|
929 | from: "**/*",
|
930 | // Terser skip this file for minimization
|
931 | info: { minimized: true },
|
932 | },
|
933 | ],
|
934 | }),
|
935 | ],
|
936 | };
|
937 | ```
|
938 |
|
939 | **webpack.config.js**
|
940 |
|
941 | ```js
|
942 | module.exports = {
|
943 | plugins: [
|
944 | new CopyPlugin({
|
945 | patterns: [
|
946 | "relative/path/to/file.ext",
|
947 | {
|
948 | from: "**/*",
|
949 | // Terser skip this file for minimization
|
950 | info: (file) => ({ minimized: true }),
|
951 | },
|
952 | ],
|
953 | }),
|
954 | ],
|
955 | };
|
956 | ```
|
957 |
|
958 | ### Options
|
959 |
|
960 | - [`concurrency`](#concurrency)
|
961 |
|
962 | #### `concurrency`
|
963 |
|
964 | type:
|
965 |
|
966 | ```ts
|
967 | type concurrency = number;
|
968 | ```
|
969 |
|
970 | default: `100`
|
971 |
|
972 | limits the number of simultaneous requests to fs
|
973 |
|
974 | **webpack.config.js**
|
975 |
|
976 | ```js
|
977 | module.exports = {
|
978 | plugins: [
|
979 | new CopyPlugin({
|
980 | patterns: [...patterns],
|
981 | options: { concurrency: 50 },
|
982 | }),
|
983 | ],
|
984 | };
|
985 | ```
|
986 |
|
987 | ### Examples
|
988 |
|
989 | #### Different variants `from` (`glob`, `file` or `dir`).
|
990 |
|
991 | Take for example the following file structure:
|
992 |
|
993 | ```
|
994 | src/directory-nested/deep-nested/deepnested-file.txt
|
995 | src/directory-nested/nested-file.txt
|
996 | ```
|
997 |
|
998 | ##### From is a Glob
|
999 |
|
1000 | Everything that you specify in `from` will be included in the result:
|
1001 |
|
1002 | **webpack.config.js**
|
1003 |
|
1004 | ```js
|
1005 | module.exports = {
|
1006 | plugins: [
|
1007 | new CopyPlugin({
|
1008 | patterns: [
|
1009 | {
|
1010 | from: "src/directory-nested/**/*",
|
1011 | },
|
1012 | ],
|
1013 | }),
|
1014 | ],
|
1015 | };
|
1016 | ```
|
1017 |
|
1018 | Result:
|
1019 |
|
1020 | ```txt
|
1021 | src/directory-nested/deep-nested/deepnested-file.txt,
|
1022 | src/directory-nested/nested-file.txt
|
1023 | ```
|
1024 |
|
1025 | If you want only content `src/directory-nested/`, you should only indicate `glob` in `from`. The path to the folder in which the search should take place, should be moved to `context`.
|
1026 |
|
1027 | **webpack.config.js**
|
1028 |
|
1029 | ```js
|
1030 | module.exports = {
|
1031 | plugins: [
|
1032 | new CopyPlugin({
|
1033 | patterns: [
|
1034 | {
|
1035 | from: "**/*",
|
1036 | context: path.resolve(__dirname, "src", "directory-nested"),
|
1037 | },
|
1038 | ],
|
1039 | }),
|
1040 | ],
|
1041 | };
|
1042 | ```
|
1043 |
|
1044 | Result:
|
1045 |
|
1046 | ```txt
|
1047 | deep-nested/deepnested-file.txt,
|
1048 | nested-file.txt
|
1049 | ```
|
1050 |
|
1051 | ##### From is a Dir
|
1052 |
|
1053 | **webpack.config.js**
|
1054 |
|
1055 | ```js
|
1056 | module.exports = {
|
1057 | plugins: [
|
1058 | new CopyPlugin({
|
1059 | patterns: [
|
1060 | {
|
1061 | from: path.resolve(__dirname, "src", "directory-nested"),
|
1062 | },
|
1063 | ],
|
1064 | }),
|
1065 | ],
|
1066 | };
|
1067 | ```
|
1068 |
|
1069 | Result:
|
1070 |
|
1071 | ```txt
|
1072 | deep-nested/deepnested-file.txt,
|
1073 | nested-file.txt
|
1074 | ```
|
1075 |
|
1076 | Technically, this is `**/*` with a predefined context equal to the specified directory.
|
1077 |
|
1078 | **webpack.config.js**
|
1079 |
|
1080 | ```js
|
1081 | module.exports = {
|
1082 | plugins: [
|
1083 | new CopyPlugin({
|
1084 | patterns: [
|
1085 | {
|
1086 | from: "**/*",
|
1087 | context: path.resolve(__dirname, "src", "directory-nested"),
|
1088 | },
|
1089 | ],
|
1090 | }),
|
1091 | ],
|
1092 | };
|
1093 | ```
|
1094 |
|
1095 | Result:
|
1096 |
|
1097 | ```txt
|
1098 | deep-nested/deepnested-file.txt,
|
1099 | nested-file.txt
|
1100 | ```
|
1101 |
|
1102 | ##### From is a File
|
1103 |
|
1104 | ```js
|
1105 | module.exports = {
|
1106 | plugins: [
|
1107 | new CopyPlugin({
|
1108 | patterns: [
|
1109 | {
|
1110 | from: path.resolve(
|
1111 | __dirname,
|
1112 | "src",
|
1113 | "directory-nested",
|
1114 | "nested-file.txt"
|
1115 | ),
|
1116 | },
|
1117 | ],
|
1118 | }),
|
1119 | ],
|
1120 | };
|
1121 | ```
|
1122 |
|
1123 | Result:
|
1124 |
|
1125 | ```txt
|
1126 | nested-file.txt
|
1127 | ```
|
1128 |
|
1129 | Technically, this is a filename with a predefined context equal to `path.dirname(pathToFile)`.
|
1130 |
|
1131 | **webpack.config.js**
|
1132 |
|
1133 | ```js
|
1134 | module.exports = {
|
1135 | plugins: [
|
1136 | new CopyPlugin({
|
1137 | patterns: [
|
1138 | {
|
1139 | from: "nested-file.txt",
|
1140 | context: path.resolve(__dirname, "src", "directory-nested"),
|
1141 | },
|
1142 | ],
|
1143 | }),
|
1144 | ],
|
1145 | };
|
1146 | ```
|
1147 |
|
1148 | Result:
|
1149 |
|
1150 | ```txt
|
1151 | nested-file.txt
|
1152 | ```
|
1153 |
|
1154 | #### Ignoring files
|
1155 |
|
1156 | **webpack.config.js**
|
1157 |
|
1158 | ```js
|
1159 | module.exports = {
|
1160 | plugins: [
|
1161 | new CopyPlugin({
|
1162 | patterns: [
|
1163 | {
|
1164 | from: path.posix.join(
|
1165 | path.resolve(__dirname, "src").replace(/\\/g, "/"),
|
1166 | "**/*"
|
1167 | ),
|
1168 | globOptions: {
|
1169 | ignore: [
|
1170 | // Ignore all `txt` files
|
1171 | "**/*.txt",
|
1172 | // Ignore all files in all subdirectories
|
1173 | "**/subdir/**",
|
1174 | ],
|
1175 | },
|
1176 | },
|
1177 | ],
|
1178 | }),
|
1179 | ],
|
1180 | };
|
1181 | ```
|
1182 |
|
1183 | #### Flatten copy
|
1184 |
|
1185 | Removes all directory references and only copies file names.
|
1186 |
|
1187 | > ⚠️ If files have the same name, the result is non-deterministic.
|
1188 |
|
1189 | **webpack.config.js**
|
1190 |
|
1191 | ```js
|
1192 | module.exports = {
|
1193 | plugins: [
|
1194 | new CopyPlugin({
|
1195 | patterns: [
|
1196 | {
|
1197 | from: "src/**/*",
|
1198 | to: "[name][ext]",
|
1199 | },
|
1200 | ],
|
1201 | }),
|
1202 | ],
|
1203 | };
|
1204 | ```
|
1205 |
|
1206 | Result:
|
1207 |
|
1208 | ```txt
|
1209 | file-1.txt
|
1210 | file-2.txt
|
1211 | nested-file.txt
|
1212 | ```
|
1213 |
|
1214 | #### Copy in new directory
|
1215 |
|
1216 | **webpack.config.js**
|
1217 |
|
1218 | ```js
|
1219 | module.exports = {
|
1220 | plugins: [
|
1221 | new CopyPlugin({
|
1222 | patterns: [
|
1223 | {
|
1224 | // When copying files starting with a dot, must specify the toType option
|
1225 | // toType: "file",
|
1226 | to({ context, absoluteFilename }) {
|
1227 | return `newdirectory/${path.relative(context, absoluteFilename)}`;
|
1228 | },
|
1229 | from: "directory",
|
1230 | },
|
1231 | ],
|
1232 | }),
|
1233 | ],
|
1234 | };
|
1235 | ```
|
1236 |
|
1237 | Result:
|
1238 |
|
1239 | ```txt
|
1240 | "newdirectory/file-1.txt",
|
1241 | "newdirectory/nestedfile.txt",
|
1242 | "newdirectory/nested/deep-nested/deepnested.txt",
|
1243 | "newdirectory/nested/nestedfile.txt",
|
1244 | ```
|
1245 |
|
1246 | #### Skip running JavaScript files through a minimizer
|
1247 |
|
1248 | Useful if you need to simply copy `*.js` files to destination "as is" without evaluating and minimizing them using Terser.
|
1249 |
|
1250 | **webpack.config.js**
|
1251 |
|
1252 | ```js
|
1253 | module.exports = {
|
1254 | plugins: [
|
1255 | new CopyPlugin({
|
1256 | patterns: [
|
1257 | "relative/path/to/file.ext",
|
1258 | {
|
1259 | from: "**/*",
|
1260 | // Terser skip this file for minimization
|
1261 | info: { minimized: true },
|
1262 | },
|
1263 | ],
|
1264 | }),
|
1265 | ],
|
1266 | };
|
1267 | ```
|
1268 |
|
1269 | ##### `yarn workspaces` and `monorepos`
|
1270 |
|
1271 | When using `yarn workspaces` or` monorepos`, relative copy paths from node_modules can be broken due to the way packages are hoisting.
|
1272 | To avoid this, should explicitly specify where to copy the files from using `require.resolve`.
|
1273 |
|
1274 | **webpack.config.js**
|
1275 |
|
1276 | ```js
|
1277 | module.exports = {
|
1278 | plugins: [
|
1279 | new CopyPlugin({
|
1280 | patterns: [
|
1281 | {
|
1282 | from: `${path.dirname(
|
1283 | require.resolve(`${moduleName}/package.json`)
|
1284 | )}/target`,
|
1285 | to: "target",
|
1286 | },
|
1287 | ],
|
1288 | }),
|
1289 | ],
|
1290 | };
|
1291 | ```
|
1292 |
|
1293 | ## Contributing
|
1294 |
|
1295 | Please take a moment to read our contributing guidelines if you haven't yet done so.
|
1296 |
|
1297 | [CONTRIBUTING](./.github/CONTRIBUTING.md)
|
1298 |
|
1299 | ## License
|
1300 |
|
1301 | [MIT](./LICENSE)
|
1302 |
|
1303 | [npm]: https://img.shields.io/npm/v/copy-webpack-plugin.svg
|
1304 | [npm-url]: https://npmjs.com/package/copy-webpack-plugin
|
1305 | [node]: https://img.shields.io/node/v/copy-webpack-plugin.svg
|
1306 | [node-url]: https://nodejs.org
|
1307 | [deps]: https://david-dm.org/webpack-contrib/copy-webpack-plugin.svg
|
1308 | [deps-url]: https://david-dm.org/webpack-contrib/copy-webpack-plugin
|
1309 | [tests]: https://github.com/webpack-contrib/copy-webpack-plugin/workflows/copy-webpack-plugin/badge.svg
|
1310 | [tests-url]: https://github.com/webpack-contrib/copy-webpack-plugin/actions
|
1311 | [cover]: https://codecov.io/gh/webpack-contrib/copy-webpack-plugin/branch/master/graph/badge.svg
|
1312 | [cover-url]: https://codecov.io/gh/webpack-contrib/copy-webpack-plugin
|
1313 | [chat]: https://img.shields.io/badge/gitter-webpack%2Fwebpack-brightgreen.svg
|
1314 | [chat-url]: https://gitter.im/webpack/webpack
|
1315 | [size]: https://packagephobia.now.sh/badge?p=copy-webpack-plugin
|
1316 | [size-url]: https://packagephobia.now.sh/result?p=copy-webpack-plugin
|
1317 | [glob-options]: https://github.com/sindresorhus/globby#options
|