{"id":32447757,"url":"https://github.com/webpack/copy-webpack-plugin","last_synced_at":"2026-01-12T02:25:00.588Z","repository":{"id":1952875,"uuid":"45010048","full_name":"webpack/copy-webpack-plugin","owner":"webpack","description":"Copy files and directories with webpack","archived":false,"fork":false,"pushed_at":"2025-11-07T12:25:59.000Z","size":3897,"stargazers_count":2854,"open_issues_count":7,"forks_count":285,"subscribers_count":31,"default_branch":"main","last_synced_at":"2025-11-16T02:15:58.415Z","etag":null,"topics":["copy","file","files","filesystem","glob","webpack","webpack-plugin"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/webpack.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"open_collective":"webpack"}},"created_at":"2015-10-27T01:53:16.000Z","updated_at":"2025-11-11T09:37:35.000Z","dependencies_parsed_at":"2024-02-19T13:30:45.382Z","dependency_job_id":"d5333fa1-7dec-495a-affa-5f77e5ec5403","html_url":"https://github.com/webpack/copy-webpack-plugin","commit_stats":{"total_commits":469,"total_committers":64,"mean_commits":7.328125,"dds":0.7867803837953091,"last_synced_commit":"a146720315edd22128b975278efce451396bcaab"},"previous_names":["kevlened/copy-webpack-plugin","webpack/copy-webpack-plugin"],"tags_count":75,"template":false,"template_full_name":null,"purl":"pkg:github/webpack/copy-webpack-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webpack%2Fcopy-webpack-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webpack%2Fcopy-webpack-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webpack%2Fcopy-webpack-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webpack%2Fcopy-webpack-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/webpack","download_url":"https://codeload.github.com/webpack/copy-webpack-plugin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webpack%2Fcopy-webpack-plugin/sbom","scorecard":{"id":557506,"data":{"date":"2025-07-28","repo":{"name":"github.com/webpack-contrib/copy-webpack-plugin","commit":"1ba5030573050badb2125a729b848a89972db796"},"scorecard":{"version":"v5.2.1-26-g4feedb85","commit":"4feedb857ab8d82158aa9774bf8054df41992180"},"score":6.6,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/4feedb857ab8d82158aa9774bf8054df41992180/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":7,"reason":"Found 22/28 approved changesets -- score normalized to 7","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/4feedb857ab8d82158aa9774bf8054df41992180/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/4feedb857ab8d82158aa9774bf8054df41992180/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":7,"reason":"8 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 7","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/4feedb857ab8d82158aa9774bf8054df41992180/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/4feedb857ab8d82158aa9774bf8054df41992180/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":10,"reason":"GitHub workflow tokens follow principle of least privilege","details":["Info: topLevel 'contents' permission set to 'read': .github/workflows/dependency-review.yml:5","Info: topLevel 'contents' permission set to 'read': .github/workflows/nodejs.yml:14","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/4feedb857ab8d82158aa9774bf8054df41992180/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":4,"reason":"dependency not pinned by hash detected -- score normalized to 4","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/dependency-review.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/webpack-contrib/copy-webpack-plugin/dependency-review.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/dependency-review.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/webpack-contrib/copy-webpack-plugin/dependency-review.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/webpack-contrib/copy-webpack-plugin/nodejs.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:40: update your workflow using https://app.stepsecurity.io/secureworkflow/webpack-contrib/copy-webpack-plugin/nodejs.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:84: update your workflow using https://app.stepsecurity.io/secureworkflow/webpack-contrib/copy-webpack-plugin/nodejs.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:87: update your workflow using https://app.stepsecurity.io/secureworkflow/webpack-contrib/copy-webpack-plugin/nodejs.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/nodejs.yml:103: update your workflow using https://app.stepsecurity.io/secureworkflow/webpack-contrib/copy-webpack-plugin/nodejs.yml/master?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/nodejs.yml:98","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   2 out of   3 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/4feedb857ab8d82158aa9774bf8054df41992180/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/4feedb857ab8d82158aa9774bf8054df41992180/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/4feedb857ab8d82158aa9774bf8054df41992180/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/4feedb857ab8d82158aa9774bf8054df41992180/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/4feedb857ab8d82158aa9774bf8054df41992180/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/4feedb857ab8d82158aa9774bf8054df41992180/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/4feedb857ab8d82158aa9774bf8054df41992180/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 28 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/4feedb857ab8d82158aa9774bf8054df41992180/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/4feedb857ab8d82158aa9774bf8054df41992180/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T12:44:52.437Z","repository_id":1952875,"created_at":"2025-08-20T12:44:52.437Z","updated_at":"2025-08-20T12:44:52.437Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28332298,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T00:36:25.062Z","status":"online","status_checked_at":"2026-01-12T02:00:08.677Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["copy","file","files","filesystem","glob","webpack","webpack-plugin"],"created_at":"2025-10-26T05:01:51.848Z","updated_at":"2026-01-12T02:25:00.581Z","avatar_url":"https://github.com/webpack.png","language":"JavaScript","readme":"\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://github.com/webpack/webpack\"\u003e\n    \u003cimg width=\"200\" height=\"200\"\n      src=\"https://webpack.js.org/assets/icon-square-big.svg\"\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n[![npm][npm]][npm-url]\n[![node][node]][node-url]\n[![tests][tests]][tests-url]\n[![cover][cover]][cover-url]\n[![discussion][discussion]][discussion-url]\n[![size][size]][size-url]\n\n# copy-webpack-plugin\n\nCopies existing individual files or entire directories to the build directory.\n\n## Getting Started\n\nTo begin, you'll need to install `copy-webpack-plugin`:\n\n```console\nnpm install copy-webpack-plugin --save-dev\n```\n\nor\n\n```console\nyarn add -D copy-webpack-plugin\n```\n\nor\n\n```console\npnpm add -D copy-webpack-plugin\n```\n\nThen add the plugin to your `webpack` configuration. For example:\n\n**webpack.config.js**\n\n```js\nconst CopyPlugin = require(\"copy-webpack-plugin\");\n\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        { from: \"source\", to: \"dest\" },\n        { from: \"other\", to: \"public\" },\n      ],\n    }),\n  ],\n};\n```\n\n\u003e [!NOTE]\n\u003e\n\u003e `copy-webpack-plugin` is not designed to copy files generated during the build process. Instead, it is meant to copy files that already exist in the source tree, as part of the build process.\n\n\u003e [!NOTE]\n\u003e\n\u003e If you want `webpack-dev-server` to write files to the output directory during development, you can enable the [`writeToDisk`](https://github.com/webpack/webpack-dev-middleware#writetodisk) option or use the [`write-file-webpack-plugin`](https://github.com/gajus/write-file-webpack-plugin).\n\n\u003e [!NOTE]\n\u003e\n\u003e You can get the original source filename from the [Asset Objects](https://webpack.js.org/api/stats/#asset-objects) in the webpack stats API.\n\n## Options\n\n- **[`patterns`](#patterns)**\n- **[`options`](#options-1)**\n\nThe plugin's usage:\n\n**webpack.config.js**\n\n```js\nconst CopyPlugin = require(\"copy-webpack-plugin\");\n\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        { from: \"source\", to: \"dest\" },\n        \"path/to/source\", // Absolute or relative path, can be files, directories or globs. See examples below.\n      ],\n      options: {\n        concurrency: 100,\n      },\n    }),\n  ],\n};\n```\n\n### `Patterns`\n\n- [`from`](#from)\n- [`to`](#to)\n- [`context`](#context)\n- [`globOptions`](#globoptions)\n- [`filter`](#filter)\n- [`toType`](#totype)\n- [`force`](#force)\n- [`priority`](#priority)\n- [`transform`](#transform)\n- [`transformAll`](#transformAll)\n- [`noErrorOnMissing`](#noerroronmissing)\n- [`info`](#info)\n\n#### `from`\n\nType:\n\n```ts\ntype from = string;\n```\n\nDefault: `undefined`\n\nGlob or path from where we copy files.\nGlobs follow the [fast-glob pattern-syntax](https://github.com/mrmlnc/fast-glob#pattern-syntax).\nNote: Globs must be a `string`.\n\n\u003e [!WARNING]\n\u003e\n\u003e Don't use directly `\\\\` in `from` option if it is a `glob` (i.e `path\\to\\file.ext`) option, as backslashes are treated as regular characters on UNIX systems(not as path separators).\n\u003e On Windows, both forward slashes and backslashes act as separators.\n\u003e Use `/` instead, or use Node's `path` utilities to normalize paths.\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        \"relative/path/to/file.ext\",\n        \"relative/path/to/dir\",\n        path.resolve(__dirname, \"src\", \"file.ext\"),\n        path.resolve(__dirname, \"src\", \"dir\"),\n        \"**/*\",\n        {\n          from: \"**/*\",\n        },\n        // If absolute path is a `glob` we replace backslashes with forward slashes, because only forward slashes can be used in the `glob`\n        path.posix.join(\n          path.resolve(__dirname, \"src\").replaceAll(\"\\\\\", \"/\"),\n          \"*.txt\",\n        ),\n      ],\n    }),\n  ],\n};\n```\n\n##### `For windows`\n\nIf you're using an absolute file or folder path in the `from` option on `Windows`, you can use windows path segment (`\\\\`)\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: path.resolve(__dirname, \"file.txt\"),\n        },\n      ],\n    }),\n  ],\n};\n```\n\nHowever, when writing `glob` expressions, always use forward slashes.\nSee the [fast-glob manual](https://github.com/mrmlnc/fast-glob#how-to-write-patterns-on-windows) for more details.\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          // If absolute path is a `glob` we replace backslashes with forward slashes, because only forward slashes can be used in the `glob`\n          from: path.posix.join(\n            path.resolve(__dirname, \"fixtures\").replaceAll(\"\\\\\", \"/\"),\n            \"*.txt\",\n          ),\n        },\n      ],\n    }),\n  ],\n};\n```\n\nThe behavior of the `context` option varies depending on whether the `from` value is a `glob`, `file` or `dir`.\nSee more [`examples`](#examples).\n\n#### `to`\n\nType:\n\n```ts\ntype to =\n  | string\n  | ((pathData: { context: string; absoluteFilename?: string }) =\u003e string);\n```\n\nDefault: `compiler.options.output`\n\n##### `string`\n\nSpecifies the output path.\n\n\u003e [!WARNING]\n\u003e\n\u003e Don't use directly `\\\\` in the `to` path (i.e `path\\to\\dest`) option, as backslashes are treated as regular characters on UNIX systems(not as path separators).\n\u003e On Windows, both forward slashes and backslashes act as separators.\n\u003e Use `/` instead, or use Node's `path` utilities to normalize paths.\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"**/*\",\n          to: \"relative/path/to/dest/\",\n        },\n        {\n          from: \"**/*\",\n          to: \"/absolute/path/to/dest/\",\n        },\n        {\n          from: \"**/*\",\n          to: \"[path][name].[contenthash][ext]\",\n        },\n      ],\n    }),\n  ],\n};\n```\n\n##### `function`\n\nAllows to modify the writing path.\n\n\u003e [!WARNING]\n\u003e\n\u003e Don't use directly `\\\\` in `to` (i.e `path\\to\\newFile`) option, as backslashes are treated as regular characters on UNIX systems(not as path separators).\n\u003e On Windows, both forward slashes and backslashes act as separators.\n\u003e Use `/` instead, or use Node's `path` utilities to normalize paths.\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"src/*.png\",\n          to({ context, absoluteFilename }) {\n            return \"dest/newPath/[name][ext]\";\n          },\n        },\n      ],\n    }),\n  ],\n};\n```\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"src/*.png\",\n          to({ context, absoluteFilename }) {\n            return Promise.resolve(\"dest/newPath/[name][ext]\");\n          },\n        },\n      ],\n    }),\n  ],\n};\n```\n\n#### `context`\n\nType:\n\n```ts\ntype context = string;\n```\n\nDefault: `options.context|compiler.options.context`\n\nDefines the base directory used for two purposes:\n\n1. It is prepended to the `from` path.\n\n2. It is removed from the beginning of the result path(s).\n\n\u003e [!WARNING]\n\u003e\n\u003e Don't use directly `\\\\` in `to` (i.e `path\\to\\newFile`) option, as backslashes are treated as regular characters on UNIX systems(not as path separators).\n\u003e On Windows, both forward slashes and backslashes act as separators.\n\u003e Use `/` instead, or use Node's `path` utilities to normalize paths.\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"src/*.txt\",\n          to: \"dest/\",\n          context: \"app/\",\n        },\n      ],\n    }),\n  ],\n};\n```\n\nThe `context` can be an absolute or relative path. If it's relative, then it will be converted to an absolute path based on `compiler.options.context`.\n\nYou should explicitly define `context` when `from` uses a glob pattern. Otherwise, the plugin sets it automatically based on the nature of `from`:\n\n- If `from` is a file, then `context` defaults to the file’s directory. The result path will be just the filename alone.\n\n- If `from` is a directory, `context` is set to the same directory. The result paths include the directory’s contents (including subdirectories), relative to it.\n\nThe use of `context` is illustrated by these [`examples`](#examples).\n\n#### `globOptions`\n\n\u003e [!WARNING]\n\u003e\n\u003e The _onlyDirectories_ does not work because the plugin is designed to copy files, not directories alone.\n\nType:\n\n```ts\ntype globOptions = import(\"tinyglobby\").GlobOptions;\n```\n\nDefault: `undefined`\n\nAllows you to configure the glob pattern matching library used by the plugin. [See the list of supported options][glob-options]\nTo exclude files from being copied, use the [globOptions.ignore option](https://github.com/mrmlnc/fast-glob#ignore)\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"public/**/*\",\n          globOptions: {\n            dot: true,\n            gitignore: true,\n            ignore: [\"**/file.*\", \"**/ignored-directory/**\"],\n          },\n        },\n      ],\n    }),\n  ],\n};\n```\n\n#### `filter`\n\nType:\n\n```ts\ntype filter = (filepath: string) =\u003e boolean;\n```\n\nDefault: `undefined`\n\n\u003e [!NOTE]\n\u003e\n\u003e To ignore files by path (e.g., by extension or name), prefer using the [`globOptions.ignore`] option.\n\n**webpack.config.js**\n\n```js\nconst fs = require(\"node:fs\").promise;\n\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"public/**/*\",\n          filter: async (resourcePath) =\u003e {\n            const data = await fs.promises.readFile(resourcePath);\n            const content = data.toString();\n\n            if (content === \"my-custom-content\") {\n              return false;\n            }\n\n            return true;\n          },\n        },\n      ],\n    }),\n  ],\n};\n```\n\n#### `toType`\n\nType:\n\n```ts\ntype toType = \"dir\" | \"file\" | \"template\";\n```\n\nDefault: `undefined`\n\nDetermines the type of the `to` option — whether it's a directory, file, or template.\nSometimes it is hard to say what is `to`, example `path/to/dir-with.ext`.\nIf you want to copy files in directory you should explicitly set the type to `dir`.\nIn most cases, the plugin will automatically determine the correct `type`, so you typically don't need to set this option manually.\n\n|             Name              |   Type   |   Default   | Description                                                                                                 |\n| :---------------------------: | :------: | :---------: | :---------------------------------------------------------------------------------------------------------- |\n|      **[`'dir'`](#dir)**      | `string` | `undefined` | Used `to` has no extension or ends with a `'/'`.                                                            |\n|     **[`'file'`](#file)**     | `string` | `undefined` | Used when `to` is a file path that is not a directory or template.                                          |\n| **[`'template'`](#template)** | `string` | `undefined` | Used when `to` contains [a template pattern](https://webpack.js.org/configuration/output/#template-strings) |\n\n##### `'dir'`\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"path/to/file.txt\",\n          to: \"directory/with/extension.ext\",\n          toType: \"dir\",\n        },\n      ],\n    }),\n  ],\n};\n```\n\n##### `'file'`\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"path/to/file.txt\",\n          to: \"file/without/extension\",\n          toType: \"file\",\n        },\n      ],\n    }),\n  ],\n};\n```\n\n##### `'template'`\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"src/\",\n          to: \"dest/[name].[contenthash][ext]\",\n          toType: \"template\",\n        },\n      ],\n    }),\n  ],\n};\n```\n\n#### `force`\n\nType:\n\n```ts\ntype force = boolean;\n```\n\nDefault: `false`\n\nOverwrites files that already exist in `compilation.assets` (typically added by other plugins or loaders).\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"src/**/*\",\n          to: \"dest/\",\n          force: true,\n        },\n      ],\n    }),\n  ],\n};\n```\n\n#### `priority`\n\nType:\n\n```ts\ntype priority = number;\n```\n\nDefault: `0`\n\nAllows to specify the priority of copying files with the same destination name.\nFiles for patterns with higher priority will be copied later.\nTo enable overwriting, the [`force`](#force) option must be set to `true`.\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        // Copied second and will overwrite \"dir_2/file.txt\"\n        {\n          from: \"dir_1/file.txt\",\n          to: \"newfile.txt\",\n          force: true,\n          priority: 10,\n        },\n        // Copied first\n        {\n          from: \"dir_2/file.txt\",\n          to: \"newfile.txt\",\n          priority: 5,\n        },\n      ],\n    }),\n  ],\n};\n```\n\n#### `transform`\n\nType:\n\n```ts\ntype transform =\n  | {\n      transformer: (input: string, absoluteFilename: string) =\u003e string | Buffer;\n      cache?: boolean | TransformerCacheObject | undefined;\n    }\n  | ((input: string, absoluteFilename: string) =\u003e string | Buffer);\n```\n\nDefault: `undefined`\n\nAllows you to modify the contents of a file before it is written to the output directory.\n\n##### `function`\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"src/*.png\",\n          to: \"dest/\",\n          // 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()`\n          // The `absoluteFrom` argument is a `String`, it is absolute path from where the file is being copied\n          transform(content, absoluteFrom) {\n            return optimize(content);\n          },\n        },\n      ],\n    }),\n  ],\n};\n```\n\n##### `object`\n\n|               Name                |   Default   | Description                                                                                                                                |\n| :-------------------------------: | :---------: | :----------------------------------------------------------------------------------------------------------------------------------------- |\n| **[`transformer`](#transformer)** | `undefined` | Allows you to modify the contents of the file.                                                                                             |\n|       **[`cache`](#cache)**       |   `false`   | Enables caching for `transform`. You can use `transform: { cache: { key: 'my-cache-key' } }` to manually invalidate the cache when needed. |\n\n###### `transformer`\n\nType:\n\n```ts\ntype transformer = (input: string, absoluteFilename: string) =\u003e string;\n```\n\nDefault: `undefined`\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"src/*.png\",\n          to: \"dest/\",\n          // 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()`\n          // The `absoluteFrom` argument is a `String`, it is absolute path from where the file is being copied\n          transform: {\n            transformer(content, absoluteFrom) {\n              return optimize(content);\n            },\n          },\n        },\n      ],\n    }),\n  ],\n};\n```\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"src/*.png\",\n          to: \"dest/\",\n          transform: {\n            transformer(content, path) {\n              return Promise.resolve(optimize(content));\n            },\n          },\n        },\n      ],\n    }),\n  ],\n};\n```\n\n###### `cache`\n\nType:\n\n```ts\ntype cache =\n  | boolean\n  | {\n      keys: Record\u003cstring, any\u003e;\n    }\n  | {\n      keys: (\n        defaultCacheKeys: Record\u003cstring, any\u003e,\n        absoluteFilename: string,\n      ) =\u003e Promise\u003cRecord\u003cstring, any\u003e\u003e;\n    }\n  | undefined;\n```\n\nDefault: `false`\n\n**webpack.config.js**\n\nEnable or disable caching and configure its behavior.\nBy default, the cache directory is located at: `node_modules/.cache/copy-webpack-plugin`.\n\n###### `boolean`\n\nEnables/Disable `transform` caching.\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"src/*.png\",\n          to: \"dest/\",\n          transform: {\n            transformer(content, path) {\n              return optimize(content);\n            },\n            cache: true,\n          },\n        },\n      ],\n    }),\n  ],\n};\n```\n\n##### `object`\n\nEnables `transform` caching and setup invalidation keys.\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"src/*.png\",\n          to: \"dest/\",\n          transform: {\n            transformer(content, path) {\n              return optimize(content);\n            },\n            cache: {\n              keys: {\n                // May be useful for invalidating cache based on external values\n                // For example, you can invalid cache based on `process.version` - { node: process.version }\n                key: \"value\",\n              },\n            },\n          },\n        },\n      ],\n    }),\n  ],\n};\n```\n\nYou can setup invalidation keys using a function.\n\nSimple function:\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"src/*.png\",\n          to: \"dest/\",\n          transform: {\n            transformer(content, path) {\n              return optimize(content);\n            },\n            cache: {\n              keys: (defaultCacheKeys, absoluteFrom) =\u003e {\n                const keys = getCustomCacheInvalidationKeysSync();\n\n                return {\n                  ...defaultCacheKeys,\n                  keys,\n                };\n              },\n            },\n          },\n        },\n      ],\n    }),\n  ],\n};\n```\n\nAsync function:\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"src/*.png\",\n          to: \"dest/\",\n          transform: {\n            transformer(content, path) {\n              return optimize(content);\n            },\n            cache: {\n              keys: async (defaultCacheKeys, absoluteFrom) =\u003e {\n                const keys = await getCustomCacheInvalidationKeysAsync();\n\n                return {\n                  ...defaultCacheKeys,\n                  keys,\n                };\n              },\n            },\n          },\n        },\n      ],\n    }),\n  ],\n};\n```\n\n#### `transformAll`\n\nType:\n\n```ts\ntype transformAll = (\n  data: {\n    data: Buffer;\n    sourceFilename: string;\n    absoluteFilename: string;\n  }[],\n) =\u003e string[];\n```\n\nDefault: `undefined`\n\nAllows you to modify the contents of multiple files and save the combined result into a single file.\n\n\u003e [!NOTE]\n\u003e\n\u003e The `to` option must be specified and point to a file. Only the `[contenthash]` and `[fullhash]` template strings are allowed in the filename.\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"src/**/*.txt\",\n          to: \"dest/file.txt\",\n          // The `assets` argument is an array of assets matched by the pattern `from` (\"src/**/*.txt\")\n          transformAll(assets) {\n            const result = assets.reduce((accumulator, asset) =\u003e {\n              // The asset content can be obtained from `asset.source` using `source` method.\n              // 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()`\n              const content = asset.data;\n\n              accumulator = `${accumulator}${content}\\n`;\n              return accumulator;\n            }, \"\");\n\n            return result;\n          },\n        },\n      ],\n    }),\n  ],\n};\n```\n\n### `noErrorOnMissing`\n\nType:\n\n```ts\ntype noErrorOnMissing = boolean;\n```\n\nDefault: `false`\n\nDoesn't generate an error if file(s) are missing.\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: path.resolve(__dirname, \"missing-file.txt\"),\n          noErrorOnMissing: true,\n        },\n      ],\n    }),\n  ],\n};\n```\n\n#### `info`\n\nType:\n\n```ts\ntype info =\n  | Record\u003cstring, any\u003e\n  | ((item: {\n      absoluteFilename: string;\n      sourceFilename: string;\n      filename: string;\n      toType: ToType;\n    }) =\u003e Record\u003cstring, any\u003e);\n```\n\nDefault: `undefined`\n\nAllows to add assets info.\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        \"relative/path/to/file.ext\",\n        {\n          from: \"**/*\",\n          // Terser skip this file for minification\n          info: { minimized: true },\n        },\n      ],\n    }),\n  ],\n};\n```\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        \"relative/path/to/file.ext\",\n        {\n          from: \"**/*\",\n          // Terser skip this file for minimization\n          info: (file) =\u003e ({ minimized: true }),\n        },\n      ],\n    }),\n  ],\n};\n```\n\n### Options\n\n- [`concurrency`](#concurrency)\n\n#### `concurrency`\n\ntype:\n\n```ts\ntype concurrency = number;\n```\n\nDefault: `100`\n\nLimits the number of simultaneous requests to fs.\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [...patterns],\n      options: { concurrency: 50 },\n    }),\n  ],\n};\n```\n\n### Examples\n\n#### Different variants of `from` (`glob`, `file` or `dir`).\n\nConsider the following file structure:\n\n```\nsrc/directory-nested/deep-nested/deepnested-file.txt\nsrc/directory-nested/nested-file.txt\n```\n\n##### From is a Glob\n\nEverything that you specify in `from` will be included in the result:\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"src/directory-nested/**/*\",\n        },\n      ],\n    }),\n  ],\n};\n```\n\nResult:\n\n```txt\nsrc/directory-nested/deep-nested/deepnested-file.txt,\nsrc/directory-nested/nested-file.txt\n```\n\nIf you don't want the result paths to start with `src/directory-nested/`, then you should move `src/directory-nested/` to `context`, such that only the glob pattern `**/*` remains in `from`:\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"**/*\",\n          context: path.resolve(__dirname, \"src\", \"directory-nested\"),\n        },\n      ],\n    }),\n  ],\n};\n```\n\nResult:\n\n```txt\ndeep-nested/deepnested-file.txt,\nnested-file.txt\n```\n\n##### From is a Dir\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: path.resolve(__dirname, \"src\", \"directory-nested\"),\n        },\n      ],\n    }),\n  ],\n};\n```\n\nResult:\n\n```txt\ndeep-nested/deepnested-file.txt,\nnested-file.txt\n```\n\nTechnically, this is equivalent to using `**/*` with a predefined context set to the specified directory\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"**/*\",\n          context: path.resolve(__dirname, \"src\", \"directory-nested\"),\n        },\n      ],\n    }),\n  ],\n};\n```\n\nResult:\n\n```txt\ndeep-nested/deepnested-file.txt,\nnested-file.txt\n```\n\n##### From is a File\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: path.resolve(\n            __dirname,\n            \"src\",\n            \"directory-nested\",\n            \"nested-file.txt\",\n          ),\n        },\n      ],\n    }),\n  ],\n};\n```\n\nResult:\n\n```txt\nnested-file.txt\n```\n\nTechnically, this is a filename with a predefined context equal to the file's directory `path.dirname(pathToFile)`.\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"nested-file.txt\",\n          context: path.resolve(__dirname, \"src\", \"directory-nested\"),\n        },\n      ],\n    }),\n  ],\n};\n```\n\nResult:\n\n```txt\nnested-file.txt\n```\n\n#### Ignoring files\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: path.posix.join(\n            path.resolve(__dirname, \"src\").replaceAll(\"\\\\\", \"/\"),\n            \"**/*\",\n          ),\n          globOptions: {\n            ignore: [\n              // Ignore all `txt` files\n              \"**/*.txt\",\n              // Ignore all files in all subdirectories\n              \"**/subdir/**\",\n            ],\n          },\n        },\n      ],\n    }),\n  ],\n};\n```\n\n#### Flatten copy\n\nRemoves all directory references and copies only file names.\n\n\u003e [!WARNING]\n\u003e\n\u003e If files have the same name, the result is non-deterministic.\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: \"src/**/*\",\n          to: \"[name][ext]\",\n        },\n      ],\n    }),\n  ],\n};\n```\n\nResult:\n\n```txt\nfile-1.txt\nfile-2.txt\nnested-file.txt\n```\n\n#### Copy in new directory\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          // When copying files starting with a dot, must specify the toType option\n          // toType: \"file\",\n          to({ context, absoluteFilename }) {\n            return `newdirectory/${path.relative(context, absoluteFilename)}`;\n          },\n          from: \"directory\",\n        },\n      ],\n    }),\n  ],\n};\n```\n\nResult:\n\n```txt\n\"newdirectory/file-1.txt\",\n\"newdirectory/nestedfile.txt\",\n\"newdirectory/nested/deep-nested/deepnested.txt\",\n\"newdirectory/nested/nestedfile.txt\",\n```\n\n#### Skip running JavaScript files through a minimizer\n\nUseful if you need to simply copy `*.js` files to destination \"as is\" without evaluating and minimizing them using Terser.\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        \"relative/path/to/file.ext\",\n        {\n          from: \"**/*\",\n          // Terser skip this file for minimization\n          info: { minimized: true },\n        },\n      ],\n    }),\n  ],\n};\n```\n\n##### `yarn workspaces` and `monorepos`\n\nWhen using `yarn workspaces` or` monorepos`, relative copy paths from `node_modules` can be broken due to the way packages are hoisting.\nTo avoid this, you should explicitly specify where to copy the files from; by using `require.resolve`.\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  plugins: [\n    new CopyPlugin({\n      patterns: [\n        {\n          from: `${path.dirname(\n            require.resolve(`${moduleName}/package.json`),\n          )}/target`,\n          to: \"target\",\n        },\n      ],\n    }),\n  ],\n};\n```\n\n## Contributing\n\nWe welcome all contributions!\n\nIf you are new here, please take a moment to review our contributing guidelines before submitting issues or pull requests.\n\n[CONTRIBUTING](https://github.com/webpack/copy-webpack-plugin?tab=contributing-ov-file#contributing)\n\n## License\n\n[MIT](./LICENSE)\n\n[npm]: https://img.shields.io/npm/v/copy-webpack-plugin.svg\n[npm-url]: https://npmjs.com/package/copy-webpack-plugin\n[node]: https://img.shields.io/node/v/copy-webpack-plugin.svg\n[node-url]: https://nodejs.org\n[tests]: https://github.com/webpack/copy-webpack-plugin/workflows/copy-webpack-plugin/badge.svg\n[tests-url]: https://github.com/webpack/copy-webpack-plugin/actions\n[cover]: https://codecov.io/gh/webpack/copy-webpack-plugin/branch/main/graph/badge.svg\n[cover-url]: https://codecov.io/gh/webpack/copy-webpack-plugin\n[discussion]: https://img.shields.io/github/discussions/webpack/webpack\n[discussion-url]: https://github.com/webpack/webpack/discussions\n[size]: https://packagephobia.now.sh/badge?p=copy-webpack-plugin\n[size-url]: https://packagephobia.now.sh/result?p=copy-webpack-plugin\n[glob-options]: https://github.com/SuperchupuDev/tinyglobby#options\n","funding_links":["https://opencollective.com/webpack"],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebpack%2Fcopy-webpack-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwebpack%2Fcopy-webpack-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebpack%2Fcopy-webpack-plugin/lists"}