{String}
Copies individual files or entire directories, which already exist, to the build directory.
To begin, you'll need to install copy-webpack-plugin:
$ npm install copy-webpack-plugin --save-dev
Then add the plugin to your webpack config. For example:
webpack.config.js
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{ from: "source", to: "dest" },
{ from: "other", to: "public" },
],
}),
],
}; ℹ️
webpack-copy-pluginis 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.
ℹ️ If you want
webpack-dev-serverto write files to the output directory during development, you can force it with thewriteToDiskoption or thewrite-file-webpack-plugin.
ℹ️ You can get the original source filename from Asset Objects.
The plugin's signature:
webpack.config.js
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{ from: "source", to: "dest" },
{ from: "other", to: "public" },
],
options: {
concurrency: 100,
},
}),
],
}; | Name | Type | Default | Description |
|---|---|---|---|
Name Type Default Description
| {String} | undefined | Glob or path from where we сopy files. |
Name Type Default Description
| {String} | compiler.options.output | Output path. |
Name Type Default Description
| {String} | options.context \|\| compiler.options.context | A path that determines how to interpret the from path. |
Name Type Default Description
| {Object} | undefined | Options passed to the glob pattern matching library including ignore option. |
Name Type Default Description
| {Function} | undefined | Allows to filter copied assets. |
Name Type Default Description
| {String} | undefined | Determinate what is to option - directory, file or template. |
Name Type Default Description
| {Boolean} | false | Overwrites files already in compilation.assets (usually added by other plugins/loaders). |
Name Type Default Description
| {Boolean} | false | Removes all directory references and only copies file names. |
Name Type Default Description
| {Function} | undefined | Allows to modify the file contents. |
Name Type Default Description
| {Boolean\|String\|Object} | false | Enable transform caching. You can use { cache: { key: 'my-cache-key' } } to invalidate the cache. |
Name Type Default Description
| {Function} | undefined | Allows to modify the writing path. |
Name Type Default Description
| {Boolean} | false | Doesn't generate an error on missing file(s). |
fromType: String Default: undefined
Glob or path from where we сopy files. Globs accept fast-glob pattern-syntax. Glob can only be a string.
⚠️ Don't use directly
\\infromoption if it is aglob(i.epath\to\file.ext) option because on UNIX the backslash is a valid character inside a path component, i.e., it's not a separator. On Windows, the forward slash and the backward slash are both separators. Instead please use/.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
"relative/path/to/file.ext",
"relative/path/to/dir",
path.resolve(__dirname, "src", "file.ext"),
path.resolve(__dirname, "src", "dir"),
"**/*",
{
from: "**/*",
},
// If absolute path is a `glob` we replace backslashes with forward slashes, because only forward slashes can be used in the `glob`
path.posix.join(
path.resolve(__dirname, "src").replace(/\\/g, "/"),
"*.txt"
),
],
}),
],
}; For windowsIf you define from as absolute file path or absolute folder path on Windows, you can use windows path segment (\\)
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, "file.txt"),
},
],
}),
],
}; But you should always use forward-slashes in glob expressions See fast-glob manual.
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
// If absolute path is a `glob` we replace backslashes with forward slashes, because only forward slashes can be used in the `glob`
from: path.posix.join(
path.resolve(__dirname, "fixtures").replace(/\\/g, "/"),
"*.txt"
),
},
],
}),
],
}; The context behaves differently depending on what the from is (glob, file or dir). More examples
toType: String Default: compiler.options.output
Output path.
⚠️ Don't use directly
\\into(i.epath\to\dest) option because on UNIX the backslash is a valid character inside a path component, i.e., it's not a separator. On Windows, the forward slash and the backward slash are both separators. Instead please use/orpathmethods.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "**/*",
to: "relative/path/to/dest/",
},
{
from: "**/*",
to: "/absolute/path/to/dest/",
},
{
from: "**/*",
to: "[path][name].[contenthash].[ext]",
},
],
}),
],
}; contextType: String Default: options.context|compiler.options.context
A path that determines how to interpret the from path.
⚠️ Don't use directly
\\incontext(i.epath\to\context) option because on UNIX the backslash is a valid character inside a path component, i.e., it's not a separator. On Windows, the forward slash and the backward slash are both separators. Instead please use/orpathmethods.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.txt",
to: "dest/",
context: "app/",
},
],
}),
],
}; 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
Also, context indicates how to interpret the search results. Further, he is considered in this role.
To determine the structure from which the found resources will be copied to the destination folder, the context option is used.
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.
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.
If from is a glob, then regardless of the context option, the result will be the structure specified in the from option
More examples
globOptionsType: Object Default: undefined
Allows to configute the glob pattern matching library used by the plugin. See the list of supported options To exclude files from the selection, you should use globOptions.ignore option
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "public/**/*",
globOptions: {
dot: true,
gitignore: true,
ignore: ["**/file.*", "**/ignored-directory/**"],
},
},
],
}),
],
}; filterType: Function Default: undefined
ℹ️ To ignore files by path please use the [
globOptions.ignore](https://github.com/webpack-contrib/copy-webpack-plugin/blob/master/(#globoptions) option.
webpack.config.js
const fs = require("fs").promise;
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "public/**/*",
filter: async (resourcePath) => {
const data = await fs.promises.readFile(resourcePath);
const content = data.toString();
if (content === "my-custom-content") {
return false;
}
return true;
},
},
],
}),
],
}; toTypeType: String Default: undefined
Determinate what is to option - directory, file or template. Sometimes it is hard to say what is to, example path/to/dir-with.ext. If you want to copy files in directory you need use dir option. We try to automatically determine the type so you most likely do not need this option.
| Name | Type | Default | Description |
|---|---|---|---|
Name Type Default Description
| {String} | undefined | If to has no extension or ends on '/' |
Name Type Default Description
| {String} | undefined | If to is not a directory and is not a template |
Name Type Default Description
| {String} | undefined | If to contains a template pattern |
'dir'webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "path/to/file.txt",
to: "directory/with/extension.ext",
toType: "dir",
},
],
}),
],
}; 'file'webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "path/to/file.txt",
to: "file/without/extension",
toType: "file",
},
],
}),
],
}; 'template'webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/",
to: "dest/[name].[hash].[ext]",
toType: "template",
},
],
}),
],
}; forceType: Boolean Default: false
Overwrites files already in compilation.assets (usually added by other plugins/loaders).
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/**/*",
to: "dest/",
force: true,
},
],
}),
],
}; flattenType: Boolean Default: false
Removes all directory references and only copies file names.
⚠️ If files have the same name, the result is non-deterministic.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/**/*",
to: "dest/",
flatten: true,
},
],
}),
],
}; transformType: Function Default: undefined
Allows to modify the file contents.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
// 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()`
// The `absoluteFrom` argument is a `String`, it is absolute path from where the file is being copied
transform(content, absoluteFrom) {
return optimize(content);
},
},
],
}),
],
}; webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transform(content, path) {
return Promise.resolve(optimize(content));
},
},
],
}),
],
}; cacheTransformType: Boolean|String|Object Default: false
Enable/disable and configure caching. Default path to cache directory: node_modules/.cache/copy-webpack-plugin.
BooleanEnables/Disable transform caching.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transform(content, path) {
return optimize(content);
},
cacheTransform: true,
},
],
}),
],
}; StringEnables transform caching and setup cache directory.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transform(content, path) {
return optimize(content);
},
// Should be absolute
cacheTransform: path.resolve(__dirname, "cache-directory"),
},
],
}),
],
}; ObjectEnables transform caching and setup cache directory and invalidation keys.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transform(content, path) {
return optimize(content);
},
cacheTransform: {
directory: path.resolve(__dirname, "cache-directory"),
keys: {
// May be useful for invalidating cache based on external values
// For example, you can invalid cache based on `process.version` - { node: process.version }
key: "value",
},
},
},
],
}),
],
}; You can setup invalidation keys using a function.
Simple function:
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transform(content, path) {
return optimize(content);
},
cacheTransform: {
directory: path.resolve(__dirname, "cache-directory"),
keys: (defaultCacheKeys, absoluteFrom) => {
const keys = getCustomCacheInvalidationKeysSync();
return {
...defaultCacheKeys,
keys,
};
},
},
},
],
}),
],
}; Async function:
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transform(content, path) {
return optimize(content);
},
cacheTransform: {
directory: path.resolve(__dirname, "cache-directory"),
keys: async (defaultCacheKeys, absoluteFrom) => {
const keys = await getCustomCacheInvalidationKeysAsync();
return {
...defaultCacheKeys,
keys,
};
},
},
},
],
}),
],
}; transformPathType: Function Default: undefined
Allows to modify the writing path.
⚠️ Don't return directly
\\intransformPath(i.epath\to\newFile) option because on UNIX the backslash is a valid character inside a path component, i.e., it's not a separator. On Windows, the forward slash and the backward slash are both separators. Instead please use/orpathmethods.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transformPath(targetPath, absolutePath) {
return "newPath";
},
},
],
}),
],
}; webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transformPath(targetPath, absolutePath) {
return Promise.resolve("newPath");
},
},
],
}),
],
}; noErrorOnMissingType: Boolean Default: false
Doesn't generate an error on missing file(s);
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, "missing-file.txt"),
noErrorOnMissing: true,
},
],
}),
],
}; | Name | Type | Default | Description |
|---|---|---|---|
Name Type Default Description
| {Number} | 100 | Limits the number of simultaneous requests to fs |
concurrencylimits the number of simultaneous requests to fs
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [...patterns],
options: { concurrency: 50 },
}),
],
}; from (glob, file or dir).Take for example the following file structure:
src/directory-nested/deep-nested/deepnested-file.txt
src/directory-nested/nested-file.txt
Everything that you specify in from will be included in the result:
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/directory-nested/**/*",
},
],
}),
],
}; Result:
src/directory-nested/deep-nested/deepnested-file.txt,
src/directory-nested/nested-file.txt
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.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "**/*",
context: path.resolve(__dirname, "src", "directory-nested"),
},
],
}),
],
}; Result:
deep-nested/deepnested-file.txt,
nested-file.txt
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, "src", "directory-nested"),
},
],
}),
],
}; Result:
deep-nested/deepnested-file.txt,
nested-file.txt
Technically, this is **/* with a predefined context equal to the specified directory.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "**/*",
context: path.resolve(__dirname, "src", "directory-nested"),
},
],
}),
],
}; Result:
deep-nested/deepnested-file.txt,
nested-file.txt
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: path.resolve(
__dirname,
"src",
"directory-nested",
"nested-file.txt"
),
},
],
}),
],
}; Result:
nested-file.txt
Technically, this is a filename with a predefined context equal to path.dirname(pathToFile).
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "nested-file.txt",
context: path.resolve(__dirname, "src", "directory-nested"),
},
],
}),
],
}; Result:
nested-file.txt
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: path.posix.join(
path.resolve(__dirname, "src").replace(/\\/g, "/"),
"**/*"
),
globOptions: {
ignore: [
// Ignore all `txt` files
"**/*.txt",
// Ignore all files in all subdirectories
"**/subdir/**",
],
},
},
],
}),
],
}; Please take a moment to read our contributing guidelines if you haven't yet done so.