UNPKG

27.6 kBMarkdownView Raw
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
18Copies individual files or entire directories, which already exist, to the build directory.
19
20## Getting Started
21
22To begin, you'll need to install `copy-webpack-plugin`:
23
24```console
25npm install copy-webpack-plugin --save-dev
26```
27
28or
29
30```console
31yarn add -D copy-webpack-plugin
32```
33
34or
35
36```console
37pnpm add -D copy-webpack-plugin
38```
39
40Then add the plugin to your `webpack` config. For example:
41
42**webpack.config.js**
43
44```js
45const CopyPlugin = require("copy-webpack-plugin");
46
47module.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
70The plugin's signature:
71
72**webpack.config.js**
73
74```js
75const CopyPlugin = require("copy-webpack-plugin");
76
77module.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
109Type:
110
111```ts
112type from = string;
113```
114
115Default: `undefined`
116
117Glob or path from where we copy files.
118Globs accept [fast-glob pattern-syntax](https://github.com/mrmlnc/fast-glob#pattern-syntax).
119Glob 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
128module.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
153If you define `from` as absolute file path or absolute folder path on `Windows`, you can use windows path segment (`\\`)
154
155```js
156module.exports = {
157 plugins: [
158 new CopyPlugin({
159 patterns: [
160 {
161 from: path.resolve(__dirname, "file.txt"),
162 },
163 ],
164 }),
165 ],
166};
167```
168
169But you should always use forward-slashes in `glob` expressions
170See [fast-glob manual](https://github.com/mrmlnc/fast-glob#how-to-write-patterns-on-windows).
171
172```js
173module.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
190The `context` behaves differently depending on what the `from` is (`glob`, `file` or `dir`).
191More [`examples`](#examples)
192
193#### `to`
194
195Type:
196
197```ts
198type to =
199 | string
200 | ((pathData: { context: string; absoluteFilename?: string }) => string);
201```
202
203Default: `compiler.options.output`
204
205##### `string`
206
207Output 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
216module.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
240Allows 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
249module.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
268module.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
286Type:
287
288```ts
289type context = string;
290```
291
292Default: `options.context|compiler.options.context`
293
294A 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
303module.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
318The `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
320To determine the structure from which the found resources will be copied to the destination folder, the `context` option is used.
321
322If `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
324If `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
326If `from` is a glob, then regardless of the `context` option, the result will be the structure specified in the `from` option
327
328More [`examples`](#examples)
329
330#### `globOptions`
331
332Type:
333
334```ts
335type globOptions = import("globby").Options;
336```
337
338Default: `undefined`
339
340Allows to configure the glob pattern matching library used by the plugin. [See the list of supported options][glob-options]
341To 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
346module.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
366Type:
367
368```ts
369type filter = (filepath: string) => boolean;
370```
371
372Default: `undefined`
373
374> ℹ️ To ignore files by path please use the [`globOptions.ignore`](#globoptions) option.
375
376**webpack.config.js**
377
378```js
379const fs = require("fs").promise;
380
381module.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
406Type:
407
408```ts
409type toType = "dir" | "file" | "template";
410```
411
412Default: `undefined`
413
414Determinate what is `to` option - directory, file or template.
415Sometimes it is hard to say what is `to`, example `path/to/dir-with.ext`.
416If you want to copy files in directory you need use `dir` option.
417We 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
430module.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
450module.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
470module.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
487Type:
488
489```ts
490type force = boolean;
491```
492
493Default: `false`
494
495Overwrites files already in `compilation.assets` (usually added by other plugins/loaders).
496
497**webpack.config.js**
498
499```js
500module.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
517Type:
518
519```ts
520type priority = number;
521```
522
523Default: `0`
524
525Allows to specify the priority of copying files with the same destination name.
526Files for patterns with higher priority will be copied later.
527To overwrite files, the [`force`](#force) option must be enabled.
528
529**webpack.config.js**
530
531```js
532module.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
557Type:
558
559```ts
560type 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
568Default: `undefined`
569
570Allows to modify the file contents.
571
572##### `function`
573
574**webpack.config.js**
575
576```js
577module.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
605Type:
606
607```ts
608type transformer = (input: string, absoluteFilename: string) => string;
609```
610
611Default: `undefined`
612
613**webpack.config.js**
614
615```js
616module.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
640module.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
661Type:
662
663```ts
664type 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
684Default: `false`
685
686**webpack.config.js**
687
688Enable/disable and configure caching.
689Default path to cache directory: `node_modules/.cache/copy-webpack-plugin`.
690
691###### `boolean`
692
693Enables/Disable `transform` caching.
694
695**webpack.config.js**
696
697```js
698module.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
720Enables `transform` caching and setup cache directory and invalidation keys.
721
722**webpack.config.js**
723
724```js
725module.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
752You can setup invalidation keys using a function.
753
754Simple function:
755
756**webpack.config.js**
757
758```js
759module.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
789Async function:
790
791**webpack.config.js**
792
793```js
794module.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
826Type:
827
828```ts
829type transformAll = (
830 data: {
831 data: Buffer;
832 sourceFilename: string;
833 absoluteFilename: string;
834 }[]
835) => any;
836```
837
838Default: `undefined`
839
840Allows 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
847module.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
876Type:
877
878```ts
879type noErrorOnMissing = boolean;
880```
881
882Default: `false`
883
884Doesn't generate an error on missing file(s).
885
886```js
887module.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
903Type:
904
905```ts
906type 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
916Default: `undefined`
917
918Allows to add assets info.
919
920**webpack.config.js**
921
922```js
923module.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
942module.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
964type:
965
966```ts
967type concurrency = number;
968```
969
970default: `100`
971
972limits the number of simultaneous requests to fs
973
974**webpack.config.js**
975
976```js
977module.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
991Take for example the following file structure:
992
993```
994src/directory-nested/deep-nested/deepnested-file.txt
995src/directory-nested/nested-file.txt
996```
997
998##### From is a Glob
999
1000Everything that you specify in `from` will be included in the result:
1001
1002**webpack.config.js**
1003
1004```js
1005module.exports = {
1006 plugins: [
1007 new CopyPlugin({
1008 patterns: [
1009 {
1010 from: "src/directory-nested/**/*",
1011 },
1012 ],
1013 }),
1014 ],
1015};
1016```
1017
1018Result:
1019
1020```txt
1021src/directory-nested/deep-nested/deepnested-file.txt,
1022src/directory-nested/nested-file.txt
1023```
1024
1025If 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
1030module.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
1044Result:
1045
1046```txt
1047deep-nested/deepnested-file.txt,
1048nested-file.txt
1049```
1050
1051##### From is a Dir
1052
1053**webpack.config.js**
1054
1055```js
1056module.exports = {
1057 plugins: [
1058 new CopyPlugin({
1059 patterns: [
1060 {
1061 from: path.resolve(__dirname, "src", "directory-nested"),
1062 },
1063 ],
1064 }),
1065 ],
1066};
1067```
1068
1069Result:
1070
1071```txt
1072deep-nested/deepnested-file.txt,
1073nested-file.txt
1074```
1075
1076Technically, this is `**/*` with a predefined context equal to the specified directory.
1077
1078**webpack.config.js**
1079
1080```js
1081module.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
1095Result:
1096
1097```txt
1098deep-nested/deepnested-file.txt,
1099nested-file.txt
1100```
1101
1102##### From is a File
1103
1104```js
1105module.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
1123Result:
1124
1125```txt
1126nested-file.txt
1127```
1128
1129Technically, this is a filename with a predefined context equal to `path.dirname(pathToFile)`.
1130
1131**webpack.config.js**
1132
1133```js
1134module.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
1148Result:
1149
1150```txt
1151nested-file.txt
1152```
1153
1154#### Ignoring files
1155
1156**webpack.config.js**
1157
1158```js
1159module.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
1185Removes 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
1192module.exports = {
1193 plugins: [
1194 new CopyPlugin({
1195 patterns: [
1196 {
1197 from: "src/**/*",
1198 to: "[name][ext]",
1199 },
1200 ],
1201 }),
1202 ],
1203};
1204```
1205
1206Result:
1207
1208```txt
1209file-1.txt
1210file-2.txt
1211nested-file.txt
1212```
1213
1214#### Copy in new directory
1215
1216**webpack.config.js**
1217
1218```js
1219module.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
1237Result:
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
1248Useful 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
1253module.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
1271When using `yarn workspaces` or` monorepos`, relative copy paths from node_modules can be broken due to the way packages are hoisting.
1272To avoid this, should explicitly specify where to copy the files from using `require.resolve`.
1273
1274**webpack.config.js**
1275
1276```js
1277module.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
1295Please 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