You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1198 lines
30 KiB

3 months ago
  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. [![npm][npm]][npm-url]
  8. [![node][node]][node-url]
  9. [![deps][deps]][deps-url]
  10. [![tests][tests]][tests-url]
  11. [![cover][cover]][cover-url]
  12. [![chat][chat]][chat-url]
  13. [![size][size]][size-url]
  14. # copy-webpack-plugin
  15. Copies individual files or entire directories, which already exist, to the build directory.
  16. ## Getting Started
  17. To begin, you'll need to install `copy-webpack-plugin`:
  18. ```console
  19. npm install copy-webpack-plugin --save-dev
  20. ```
  21. Then add the plugin to your `webpack` config. For example:
  22. **webpack.config.js**
  23. ```js
  24. const CopyPlugin = require("copy-webpack-plugin");
  25. module.exports = {
  26. plugins: [
  27. new CopyPlugin({
  28. patterns: [
  29. { from: "source", to: "dest" },
  30. { from: "other", to: "public" },
  31. ],
  32. }),
  33. ],
  34. };
  35. ```
  36. > ℹ️ `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.
  37. > ℹ️ 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).
  38. > ℹ️ You can get the original source filename from [Asset Objects](https://webpack.js.org/api/stats/#asset-objects).
  39. ## Options
  40. | Name | Type | Description |
  41. | :-------------------------: | :-----------------------: | :--------------------------------------- |
  42. | **[`patterns`](#patterns)** | `{Array<String\|Object>}` | Specify file related patterns for plugin |
  43. | **[`options`](#options-1)** | `{Object}` | Specify options for plugin |
  44. The plugin's signature:
  45. **webpack.config.js**
  46. ```js
  47. const CopyPlugin = require("copy-webpack-plugin");
  48. module.exports = {
  49. plugins: [
  50. new CopyPlugin({
  51. patterns: [
  52. { from: "source", to: "dest" },
  53. { from: "other", to: "public" },
  54. ],
  55. options: {
  56. concurrency: 100,
  57. },
  58. }),
  59. ],
  60. };
  61. ```
  62. ### Patterns
  63. | Name | Type | Default | Description |
  64. | :-------------------------------------: | :------------------: | :---------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------- |
  65. | [`from`](#from) | `{String}` | `undefined` | Glob or path from where we copy files. |
  66. | [`to`](#to) | `{String\|Function}` | `compiler.options.output` | Output path. |
  67. | [`context`](#context) | `{String}` | `options.context \|\| compiler.options.context` | A path that determines how to interpret the `from` path. |
  68. | [`globOptions`](#globoptions) | `{Object}` | `undefined` | [Options][glob-options] passed to the glob pattern matching library including `ignore` option. |
  69. | [`filter`](#filter) | `{Function}` | `undefined` | Allows to filter copied assets. |
  70. | [`toType`](#totype) | `{String}` | `undefined` | Determinate what is `to` option - directory, file or template. |
  71. | [`force`](#force) | `{Boolean}` | `false` | Overwrites files already in `compilation.assets` (usually added by other plugins/loaders). |
  72. | [`priority`](#priority) | `{Number}` | `0` | Allows you to specify the copy priority. |
  73. | [`transform`](#transform) | `{Object}` | `undefined` | Allows to modify the file contents. Enable `transform` caching. You can use `{ transform: {cache: { key: 'my-cache-key' }} }` to invalidate the cache. |
  74. | [`transformAll`](#transformAll) | `{Function}` | `undefined` | Allows you to modify the contents of multiple files and save the result to one file. |
  75. | [`noErrorOnMissing`](#noerroronmissing) | `{Boolean}` | `false` | Doesn't generate an error on missing file(s). |
  76. | [`info`](#info) | `{Object\|Function}` | `undefined` | Allows to add assets info. |
  77. #### `from`
  78. Type: `String`
  79. Default: `undefined`
  80. Glob or path from where we copy files.
  81. Globs accept [fast-glob pattern-syntax](https://github.com/mrmlnc/fast-glob#pattern-syntax).
  82. Glob can only be a `string`.
  83. > ⚠️ 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.
  84. > On Windows, the forward slash and the backward slash are both separators.
  85. > Instead please use `/`.
  86. **webpack.config.js**
  87. ```js
  88. module.exports = {
  89. plugins: [
  90. new CopyPlugin({
  91. patterns: [
  92. "relative/path/to/file.ext",
  93. "relative/path/to/dir",
  94. path.resolve(__dirname, "src", "file.ext"),
  95. path.resolve(__dirname, "src", "dir"),
  96. "**/*",
  97. {
  98. from: "**/*",
  99. },
  100. // If absolute path is a `glob` we replace backslashes with forward slashes, because only forward slashes can be used in the `glob`
  101. path.posix.join(
  102. path.resolve(__dirname, "src").replace(/\\/g, "/"),
  103. "*.txt"
  104. ),
  105. ],
  106. }),
  107. ],
  108. };
  109. ```
  110. ##### `For windows`
  111. If you define `from` as absolute file path or absolute folder path on `Windows`, you can use windows path segment (`\\`)
  112. ```js
  113. module.exports = {
  114. plugins: [
  115. new CopyPlugin({
  116. patterns: [
  117. {
  118. from: path.resolve(__dirname, "file.txt"),
  119. },
  120. ],
  121. }),
  122. ],
  123. };
  124. ```
  125. But you should always use forward-slashes in `glob` expressions
  126. See [fast-glob manual](https://github.com/mrmlnc/fast-glob#how-to-write-patterns-on-windows).
  127. ```js
  128. module.exports = {
  129. plugins: [
  130. new CopyPlugin({
  131. patterns: [
  132. {
  133. // If absolute path is a `glob` we replace backslashes with forward slashes, because only forward slashes can be used in the `glob`
  134. from: path.posix.join(
  135. path.resolve(__dirname, "fixtures").replace(/\\/g, "/"),
  136. "*.txt"
  137. ),
  138. },
  139. ],
  140. }),
  141. ],
  142. };
  143. ```
  144. The `context` behaves differently depending on what the `from` is (`glob`, `file` or `dir`).
  145. More [`examples`](#examples)
  146. #### `to`
  147. Type: `String|Function`
  148. Default: `compiler.options.output`
  149. ##### String
  150. Output path.
  151. > ⚠️ 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.
  152. > On Windows, the forward slash and the backward slash are both separators.
  153. > Instead please use `/` or `path` methods.
  154. **webpack.config.js**
  155. ```js
  156. module.exports = {
  157. plugins: [
  158. new CopyPlugin({
  159. patterns: [
  160. {
  161. from: "**/*",
  162. to: "relative/path/to/dest/",
  163. },
  164. {
  165. from: "**/*",
  166. to: "/absolute/path/to/dest/",
  167. },
  168. {
  169. from: "**/*",
  170. to: "[path][name].[contenthash][ext]",
  171. },
  172. ],
  173. }),
  174. ],
  175. };
  176. ```
  177. ##### Function
  178. Allows to modify the writing path.
  179. > ⚠️ 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.
  180. > On Windows, the forward slash and the backward slash are both separators.
  181. > Instead please use `/` or `path` methods.
  182. **webpack.config.js**
  183. ```js
  184. module.exports = {
  185. plugins: [
  186. new CopyPlugin({
  187. patterns: [
  188. {
  189. from: "src/*.png",
  190. to({ context, absoluteFilename }) {
  191. return "dest/newPath/[name][ext]";
  192. },
  193. },
  194. ],
  195. }),
  196. ],
  197. };
  198. ```
  199. **webpack.config.js**
  200. ```js
  201. module.exports = {
  202. plugins: [
  203. new CopyPlugin({
  204. patterns: [
  205. {
  206. from: "src/*.png",
  207. to({ context, absoluteFilename }) {
  208. return Promise.resolve("dest/newPath/[name][ext]");
  209. },
  210. },
  211. ],
  212. }),
  213. ],
  214. };
  215. ```
  216. #### `context`
  217. Type: `String`
  218. Default: `options.context|compiler.options.context`
  219. A path that determines how to interpret the `from` path.
  220. > ⚠️ 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.
  221. > On Windows, the forward slash and the backward slash are both separators.
  222. > Instead please use `/` or `path` methods.
  223. **webpack.config.js**
  224. ```js
  225. module.exports = {
  226. plugins: [
  227. new CopyPlugin({
  228. patterns: [
  229. {
  230. from: "src/*.txt",
  231. to: "dest/",
  232. context: "app/",
  233. },
  234. ],
  235. }),
  236. ],
  237. };
  238. ```
  239. 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`
  240. Also, `context` indicates how to interpret the search results. Further, he is considered in this role.
  241. To determine the structure from which the found resources will be copied to the destination folder, the `context` option is used.
  242. 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.
  243. 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.
  244. If `from` is a glob, then regardless of the `context` option, the result will be the structure specified in the `from` option
  245. More [`examples`](#examples)
  246. #### `globOptions`
  247. Type: `Object`
  248. Default: `undefined`
  249. Allows to configure the glob pattern matching library used by the plugin. [See the list of supported options][glob-options]
  250. To exclude files from the selection, you should use [globOptions.ignore option](https://github.com/mrmlnc/fast-glob#ignore)
  251. **webpack.config.js**
  252. ```js
  253. module.exports = {
  254. plugins: [
  255. new CopyPlugin({
  256. patterns: [
  257. {
  258. from: "public/**/*",
  259. globOptions: {
  260. dot: true,
  261. gitignore: true,
  262. ignore: ["**/file.*", "**/ignored-directory/**"],
  263. },
  264. },
  265. ],
  266. }),
  267. ],
  268. };
  269. ```
  270. #### `filter`
  271. Type: `Function`
  272. Default: `undefined`
  273. > ℹ️ To ignore files by path please use the [`globOptions.ignore`](#globoptions) option.
  274. **webpack.config.js**
  275. ```js
  276. const fs = require("fs").promise;
  277. module.exports = {
  278. plugins: [
  279. new CopyPlugin({
  280. patterns: [
  281. {
  282. from: "public/**/*",
  283. filter: async (resourcePath) => {
  284. const data = await fs.promises.readFile(resourcePath);
  285. const content = data.toString();
  286. if (content === "my-custom-content") {
  287. return false;
  288. }
  289. return true;
  290. },
  291. },
  292. ],
  293. }),
  294. ],
  295. };
  296. ```
  297. #### `toType`
  298. Type: `String`
  299. Default: `undefined`
  300. Determinate what is `to` option - directory, file or template.
  301. Sometimes it is hard to say what is `to`, example `path/to/dir-with.ext`.
  302. If you want to copy files in directory you need use `dir` option.
  303. We try to automatically determine the `type` so you most likely do not need this option.
  304. | Name | Type | Default | Description |
  305. | :---------------------------: | :--------: | :---------: | :--------------------------------------------------------------------------------------------------- |
  306. | **[`'dir'`](#dir)** | `{String}` | `undefined` | If `to` has no extension or ends on `'/'` |
  307. | **[`'file'`](#file)** | `{String}` | `undefined` | If `to` is not a directory and is not a template |
  308. | **[`'template'`](#template)** | `{String}` | `undefined` | If `to` contains [a template pattern](https://webpack.js.org/configuration/output/#template-strings) |
  309. ##### `'dir'`
  310. **webpack.config.js**
  311. ```js
  312. module.exports = {
  313. plugins: [
  314. new CopyPlugin({
  315. patterns: [
  316. {
  317. from: "path/to/file.txt",
  318. to: "directory/with/extension.ext",
  319. toType: "dir",
  320. },
  321. ],
  322. }),
  323. ],
  324. };
  325. ```
  326. ##### `'file'`
  327. **webpack.config.js**
  328. ```js
  329. module.exports = {
  330. plugins: [
  331. new CopyPlugin({
  332. patterns: [
  333. {
  334. from: "path/to/file.txt",
  335. to: "file/without/extension",
  336. toType: "file",
  337. },
  338. ],
  339. }),
  340. ],
  341. };
  342. ```
  343. ##### `'template'`
  344. **webpack.config.js**
  345. ```js
  346. module.exports = {
  347. plugins: [
  348. new CopyPlugin({
  349. patterns: [
  350. {
  351. from: "src/",
  352. to: "dest/[name].[contenthash][ext]",
  353. toType: "template",
  354. },
  355. ],
  356. }),
  357. ],
  358. };
  359. ```
  360. #### `force`
  361. Type: `Boolean`
  362. Default: `false`
  363. Overwrites files already in `compilation.assets` (usually added by other plugins/loaders).
  364. **webpack.config.js**
  365. ```js
  366. module.exports = {
  367. plugins: [
  368. new CopyPlugin({
  369. patterns: [
  370. {
  371. from: "src/**/*",
  372. to: "dest/",
  373. force: true,
  374. },
  375. ],
  376. }),
  377. ],
  378. };
  379. ```
  380. #### `priority`
  381. Type: `Number`
  382. Default: `0`
  383. Allows to specify the priority of copying files with the same destination name.
  384. Files for patterns with higher priority will be copied later.
  385. To overwrite files, the [`force`](#force) option must be enabled.
  386. **webpack.config.js**
  387. ```js
  388. module.exports = {
  389. plugins: [
  390. new CopyPlugin({
  391. patterns: [
  392. // Copied second and will overwrite "dir_2/file.txt"
  393. {
  394. from: "dir_1/file.txt",
  395. to: "newfile.txt",
  396. force: true,
  397. priority: 10,
  398. },
  399. // Copied first
  400. {
  401. from: "dir_2/file.txt",
  402. to: "newfile.txt",
  403. priority: 5,
  404. },
  405. ],
  406. }),
  407. ],
  408. };
  409. ```
  410. #### `transform`
  411. Type: `Function|Object`
  412. Default: `undefined`
  413. Allows to modify the file contents.
  414. ##### `Function`
  415. **webpack.config.js**
  416. ```js
  417. module.exports = {
  418. plugins: [
  419. new CopyPlugin({
  420. patterns: [
  421. {
  422. from: "src/*.png",
  423. to: "dest/",
  424. // 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()`
  425. // The `absoluteFrom` argument is a `String`, it is absolute path from where the file is being copied
  426. transform(content, absoluteFrom) {
  427. return optimize(content);
  428. },
  429. },
  430. ],
  431. }),
  432. ],
  433. };
  434. ```
  435. ##### `Object`
  436. | Name | Type | Default | Description |
  437. | :-------------------------------: | :-----------------: | :---------: | :--------------------------------------------------------------------------------------------------------------- |
  438. | **[`transformer`](#transformer)** | `{Function}` | `undefined` | Allows to modify the file contents. |
  439. | **[`cache`](#cache)** | `{Boolean\|Object}` | `false` | Enable `transform` caching. You can use `transform: { cache: { key: 'my-cache-key' } }` to invalidate the cache. |
  440. ###### `transformer`
  441. Type: `Function`
  442. Default: `undefined`
  443. **webpack.config.js**
  444. ```js
  445. module.exports = {
  446. plugins: [
  447. new CopyPlugin({
  448. patterns: [
  449. {
  450. from: "src/*.png",
  451. to: "dest/",
  452. // 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()`
  453. // The `absoluteFrom` argument is a `String`, it is absolute path from where the file is being copied
  454. transform: {
  455. transformer(content, absoluteFrom) {
  456. return optimize(content);
  457. },
  458. },
  459. },
  460. ],
  461. }),
  462. ],
  463. };
  464. ```
  465. **webpack.config.js**
  466. ```js
  467. module.exports = {
  468. plugins: [
  469. new CopyPlugin({
  470. patterns: [
  471. {
  472. from: "src/*.png",
  473. to: "dest/",
  474. transform: {
  475. transformer(content, path) {
  476. return Promise.resolve(optimize(content));
  477. },
  478. },
  479. },
  480. ],
  481. }),
  482. ],
  483. };
  484. ```
  485. ###### `cache`
  486. Type: `Boolean|Object`
  487. Default: `false`
  488. **webpack.config.js**
  489. Enable/disable and configure caching.
  490. Default path to cache directory: `node_modules/.cache/copy-webpack-plugin`.
  491. ###### `Boolean`
  492. Enables/Disable `transform` caching.
  493. **webpack.config.js**
  494. ```js
  495. module.exports = {
  496. plugins: [
  497. new CopyPlugin({
  498. patterns: [
  499. {
  500. from: "src/*.png",
  501. to: "dest/",
  502. transform: {
  503. transformer(content, path) {
  504. return optimize(content);
  505. },
  506. cache: true,
  507. },
  508. },
  509. ],
  510. }),
  511. ],
  512. };
  513. ```
  514. ##### `Object`
  515. Enables `transform` caching and setup cache directory and invalidation keys.
  516. **webpack.config.js**
  517. ```js
  518. module.exports = {
  519. plugins: [
  520. new CopyPlugin({
  521. patterns: [
  522. {
  523. from: "src/*.png",
  524. to: "dest/",
  525. transform: {
  526. transformer(content, path) {
  527. return optimize(content);
  528. },
  529. cache: {
  530. directory: path.resolve(__dirname, "cache-directory"),
  531. keys: {
  532. // May be useful for invalidating cache based on external values
  533. // For example, you can invalid cache based on `process.version` - { node: process.version }
  534. key: "value",
  535. },
  536. },
  537. },
  538. },
  539. ],
  540. }),
  541. ],
  542. };
  543. ```
  544. You can setup invalidation keys using a function.
  545. Simple function:
  546. **webpack.config.js**
  547. ```js
  548. module.exports = {
  549. plugins: [
  550. new CopyPlugin({
  551. patterns: [
  552. {
  553. from: "src/*.png",
  554. to: "dest/",
  555. transform: {
  556. transformer(content, path) {
  557. return optimize(content);
  558. },
  559. cache: {
  560. directory: path.resolve(__dirname, "cache-directory"),
  561. keys: (defaultCacheKeys, absoluteFrom) => {
  562. const keys = getCustomCacheInvalidationKeysSync();
  563. return {
  564. ...defaultCacheKeys,
  565. keys,
  566. };
  567. },
  568. },
  569. },
  570. },
  571. ],
  572. }),
  573. ],
  574. };
  575. ```
  576. Async function:
  577. **webpack.config.js**
  578. ```js
  579. module.exports = {
  580. plugins: [
  581. new CopyPlugin({
  582. patterns: [
  583. {
  584. from: "src/*.png",
  585. to: "dest/",
  586. transform: {
  587. transformer(content, path) {
  588. return optimize(content);
  589. },
  590. cache: {
  591. directory: path.resolve(__dirname, "cache-directory"),
  592. keys: async (defaultCacheKeys, absoluteFrom) => {
  593. const keys = await getCustomCacheInvalidationKeysAsync();
  594. return {
  595. ...defaultCacheKeys,
  596. keys,
  597. };
  598. },
  599. },
  600. },
  601. },
  602. ],
  603. }),
  604. ],
  605. };
  606. ```
  607. #### `transformAll`
  608. Type: `Function`
  609. Default: `undefined`
  610. Allows you to modify the contents of multiple files and save the result to one file.
  611. > ℹ️ The `to` option must be specified and point to a file. It is allowed to use only `[contenthash]` and `[fullhash]` template strings.
  612. **webpack.config.js**
  613. ```js
  614. module.exports = {
  615. plugins: [
  616. new CopyPlugin({
  617. patterns: [
  618. {
  619. from: "src/**/*.txt",
  620. to: "dest/file.txt",
  621. // The `assets` argument is an assets array for the pattern.from ("src/**/*.txt")
  622. transformAll(assets) {
  623. const result = assets.reduce((accumulator, asset) => {
  624. // The asset content can be obtained from `asset.source` using `source` method.
  625. // 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()`
  626. const content = asset.data;
  627. accumulator = `${accumulator}${content}\n`;
  628. return accumulator;
  629. }, "");
  630. return result;
  631. },
  632. },
  633. ],
  634. }),
  635. ],
  636. };
  637. ```
  638. ### `noErrorOnMissing`
  639. Type: `Boolean`
  640. Default: `false`
  641. Doesn't generate an error on missing file(s).
  642. ```js
  643. module.exports = {
  644. plugins: [
  645. new CopyPlugin({
  646. patterns: [
  647. {
  648. from: path.resolve(__dirname, "missing-file.txt"),
  649. noErrorOnMissing: true,
  650. },
  651. ],
  652. }),
  653. ],
  654. };
  655. ```
  656. #### `info`
  657. Type: `Object|Function<Object>`
  658. Default: `undefined`
  659. Allows to add assets info.
  660. **webpack.config.js**
  661. ```js
  662. module.exports = {
  663. plugins: [
  664. new CopyPlugin({
  665. patterns: [
  666. "relative/path/to/file.ext",
  667. {
  668. from: "**/*",
  669. // Terser skip this file for minimization
  670. info: { minimized: true },
  671. },
  672. ],
  673. }),
  674. ],
  675. };
  676. ```
  677. **webpack.config.js**
  678. ```js
  679. module.exports = {
  680. plugins: [
  681. new CopyPlugin({
  682. patterns: [
  683. "relative/path/to/file.ext",
  684. {
  685. from: "**/*",
  686. // Terser skip this file for minimization
  687. info: (file) => ({ minimized: true }),
  688. },
  689. ],
  690. }),
  691. ],
  692. };
  693. ```
  694. ### Options
  695. | Name | Type | Default | Description |
  696. | :---------------------------: | :--------: | :-----: | :----------------------------------------------- |
  697. | [`concurrency`](#concurrency) | `{Number}` | `100` | Limits the number of simultaneous requests to fs |
  698. #### `concurrency`
  699. limits the number of simultaneous requests to fs
  700. **webpack.config.js**
  701. ```js
  702. module.exports = {
  703. plugins: [
  704. new CopyPlugin({
  705. patterns: [...patterns],
  706. options: { concurrency: 50 },
  707. }),
  708. ],
  709. };
  710. ```
  711. ### Examples
  712. #### Different variants `from` (`glob`, `file` or `dir`).
  713. Take for example the following file structure:
  714. ```
  715. src/directory-nested/deep-nested/deepnested-file.txt
  716. src/directory-nested/nested-file.txt
  717. ```
  718. ##### From is a Glob
  719. Everything that you specify in `from` will be included in the result:
  720. **webpack.config.js**
  721. ```js
  722. module.exports = {
  723. plugins: [
  724. new CopyPlugin({
  725. patterns: [
  726. {
  727. from: "src/directory-nested/**/*",
  728. },
  729. ],
  730. }),
  731. ],
  732. };
  733. ```
  734. Result:
  735. ```txt
  736. src/directory-nested/deep-nested/deepnested-file.txt,
  737. src/directory-nested/nested-file.txt
  738. ```
  739. 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`.
  740. **webpack.config.js**
  741. ```js
  742. module.exports = {
  743. plugins: [
  744. new CopyPlugin({
  745. patterns: [
  746. {
  747. from: "**/*",
  748. context: path.resolve(__dirname, "src", "directory-nested"),
  749. },
  750. ],
  751. }),
  752. ],
  753. };
  754. ```
  755. Result:
  756. ```txt
  757. deep-nested/deepnested-file.txt,
  758. nested-file.txt
  759. ```
  760. ##### From is a Dir
  761. **webpack.config.js**
  762. ```js
  763. module.exports = {
  764. plugins: [
  765. new CopyPlugin({
  766. patterns: [
  767. {
  768. from: path.resolve(__dirname, "src", "directory-nested"),
  769. },
  770. ],
  771. }),
  772. ],
  773. };
  774. ```
  775. Result:
  776. ```txt
  777. deep-nested/deepnested-file.txt,
  778. nested-file.txt
  779. ```
  780. Technically, this is `**/*` with a predefined context equal to the specified directory.
  781. **webpack.config.js**
  782. ```js
  783. module.exports = {
  784. plugins: [
  785. new CopyPlugin({
  786. patterns: [
  787. {
  788. from: "**/*",
  789. context: path.resolve(__dirname, "src", "directory-nested"),
  790. },
  791. ],
  792. }),
  793. ],
  794. };
  795. ```
  796. Result:
  797. ```txt
  798. deep-nested/deepnested-file.txt,
  799. nested-file.txt
  800. ```
  801. ##### From is a File
  802. ```js
  803. module.exports = {
  804. plugins: [
  805. new CopyPlugin({
  806. patterns: [
  807. {
  808. from: path.resolve(
  809. __dirname,
  810. "src",
  811. "directory-nested",
  812. "nested-file.txt"
  813. ),
  814. },
  815. ],
  816. }),
  817. ],
  818. };
  819. ```
  820. Result:
  821. ```txt
  822. nested-file.txt
  823. ```
  824. Technically, this is a filename with a predefined context equal to `path.dirname(pathToFile)`.
  825. **webpack.config.js**
  826. ```js
  827. module.exports = {
  828. plugins: [
  829. new CopyPlugin({
  830. patterns: [
  831. {
  832. from: "nested-file.txt",
  833. context: path.resolve(__dirname, "src", "directory-nested"),
  834. },
  835. ],
  836. }),
  837. ],
  838. };
  839. ```
  840. Result:
  841. ```txt
  842. nested-file.txt
  843. ```
  844. #### Ignoring files
  845. **webpack.config.js**
  846. ```js
  847. module.exports = {
  848. plugins: [
  849. new CopyPlugin({
  850. patterns: [
  851. {
  852. from: path.posix.join(
  853. path.resolve(__dirname, "src").replace(/\\/g, "/"),
  854. "**/*"
  855. ),
  856. globOptions: {
  857. ignore: [
  858. // Ignore all `txt` files
  859. "**/*.txt",
  860. // Ignore all files in all subdirectories
  861. "**/subdir/**",
  862. ],
  863. },
  864. },
  865. ],
  866. }),
  867. ],
  868. };
  869. ```
  870. #### Flatten copy
  871. Removes all directory references and only copies file names.
  872. > ⚠️ If files have the same name, the result is non-deterministic.
  873. **webpack.config.js**
  874. ```js
  875. module.exports = {
  876. plugins: [
  877. new CopyPlugin({
  878. patterns: [
  879. {
  880. from: "src/**/*",
  881. to: "[name][ext]",
  882. },
  883. ],
  884. }),
  885. ],
  886. };
  887. ```
  888. Result:
  889. ```txt
  890. file-1.txt
  891. file-2.txt
  892. nested-file.txt
  893. ```
  894. #### Copy in new directory
  895. **webpack.config.js**
  896. ```js
  897. module.exports = {
  898. plugins: [
  899. new CopyPlugin({
  900. patterns: [
  901. {
  902. // When copying files starting with a dot, must specify the toType option
  903. // toType: "file",
  904. to({ context, absoluteFilename }) {
  905. return `newdirectory/${path.relative(context, absoluteFilename)}`;
  906. },
  907. from: "directory",
  908. },
  909. ],
  910. }),
  911. ],
  912. };
  913. ```
  914. Result:
  915. ```txt
  916. "newdirectory/file-1.txt",
  917. "newdirectory/nestedfile.txt",
  918. "newdirectory/nested/deep-nested/deepnested.txt",
  919. "newdirectory/nested/nestedfile.txt",
  920. ```
  921. #### Skip running JavaScript files through a minimizer
  922. Useful if you need to simply copy `*.js` files to destination "as is" without evaluating and minimizing them using Terser.
  923. **webpack.config.js**
  924. ```js
  925. module.exports = {
  926. plugins: [
  927. new CopyPlugin({
  928. patterns: [
  929. "relative/path/to/file.ext",
  930. {
  931. from: "**/*",
  932. // Terser skip this file for minimization
  933. info: { minimized: true },
  934. },
  935. ],
  936. }),
  937. ],
  938. };
  939. ```
  940. ##### `yarn workspaces` and `monorepos`
  941. When using `yarn workspaces` or` monorepos`, relative copy paths from node_modules can be broken due to the way packages are hoisting.
  942. To avoid this, should explicitly specify where to copy the files from using `require.resolve`.
  943. **webpack.config.js**
  944. ```js
  945. module.exports = {
  946. plugins: [
  947. new CopyPlugin({
  948. patterns: [
  949. {
  950. from: `${path.dirname(
  951. require.resolve(`${moduleName}/package.json`)
  952. )}/target`,
  953. to: "target",
  954. },
  955. ],
  956. }),
  957. ],
  958. };
  959. ```
  960. ## Contributing
  961. Please take a moment to read our contributing guidelines if you haven't yet done so.
  962. [CONTRIBUTING](./.github/CONTRIBUTING.md)
  963. ## License
  964. [MIT](./LICENSE)
  965. [npm]: https://img.shields.io/npm/v/copy-webpack-plugin.svg
  966. [npm-url]: https://npmjs.com/package/copy-webpack-plugin
  967. [node]: https://img.shields.io/node/v/copy-webpack-plugin.svg
  968. [node-url]: https://nodejs.org
  969. [deps]: https://david-dm.org/webpack-contrib/copy-webpack-plugin.svg
  970. [deps-url]: https://david-dm.org/webpack-contrib/copy-webpack-plugin
  971. [tests]: https://github.com/webpack-contrib/copy-webpack-plugin/workflows/copy-webpack-plugin/badge.svg
  972. [tests-url]: https://github.com/webpack-contrib/copy-webpack-plugin/actions
  973. [cover]: https://codecov.io/gh/webpack-contrib/copy-webpack-plugin/branch/master/graph/badge.svg
  974. [cover-url]: https://codecov.io/gh/webpack-contrib/copy-webpack-plugin
  975. [chat]: https://img.shields.io/badge/gitter-webpack%2Fwebpack-brightgreen.svg
  976. [chat-url]: https://gitter.im/webpack/webpack
  977. [size]: https://packagephobia.now.sh/badge?p=copy-webpack-plugin
  978. [size-url]: https://packagephobia.now.sh/result?p=copy-webpack-plugin
  979. [glob-options]: https://github.com/sindresorhus/globby#options