1318 lines
27 KiB
Markdown
1318 lines
27 KiB
Markdown
<div align="center">
|
||
<a href="https://github.com/webpack/webpack">
|
||
<img width="200" height="200"
|
||
src="https://webpack.js.org/assets/icon-square-big.svg">
|
||
</a>
|
||
</div>
|
||
|
||
[![npm][npm]][npm-url]
|
||
[![node][node]][node-url]
|
||
[![deps][deps]][deps-url]
|
||
[![tests][tests]][tests-url]
|
||
[![cover][cover]][cover-url]
|
||
[![chat][chat]][chat-url]
|
||
[![size][size]][size-url]
|
||
|
||
# copy-webpack-plugin
|
||
|
||
Copies individual files or entire directories, which already exist, to the build directory.
|
||
|
||
## Getting Started
|
||
|
||
To begin, you'll need to install `copy-webpack-plugin`:
|
||
|
||
```console
|
||
npm install copy-webpack-plugin --save-dev
|
||
```
|
||
|
||
or
|
||
|
||
```console
|
||
yarn add -D copy-webpack-plugin
|
||
```
|
||
|
||
or
|
||
|
||
```console
|
||
pnpm add -D copy-webpack-plugin
|
||
```
|
||
|
||
Then add the plugin to your `webpack` config. For example:
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
const CopyPlugin = require("copy-webpack-plugin");
|
||
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{ from: "source", to: "dest" },
|
||
{ from: "other", to: "public" },
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
> ℹ️ `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.
|
||
|
||
> ℹ️ 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).
|
||
|
||
> ℹ️ You can get the original source filename from [Asset Objects](https://webpack.js.org/api/stats/#asset-objects).
|
||
|
||
## Options
|
||
|
||
- **[`patterns`](#patterns)**
|
||
- **[`options`](#options-1)**
|
||
|
||
The plugin's signature:
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
const CopyPlugin = require("copy-webpack-plugin");
|
||
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{ from: "source", to: "dest" },
|
||
"path/to/source", // absolute or relative, files/directories/globs - see below for examples
|
||
],
|
||
options: {
|
||
concurrency: 100,
|
||
},
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
### `Patterns`
|
||
|
||
- [`from`](#from)
|
||
- [`to`](#to)
|
||
- [`context`](#context)
|
||
- [`globOptions`](#globoptions)
|
||
- [`filter`](#filter)
|
||
- [`toType`](#totype)
|
||
- [`force`](#force)
|
||
- [`priority`](#priority)
|
||
- [`transform`](#transform)
|
||
- [`transformAll`](#transformAll)
|
||
- [`noErrorOnMissing`](#noerroronmissing)
|
||
- [`info`](#info)
|
||
|
||
#### `from`
|
||
|
||
Type:
|
||
|
||
```ts
|
||
type from = string;
|
||
```
|
||
|
||
Default: `undefined`
|
||
|
||
Glob or path from where we copy files.
|
||
Globs accept [fast-glob pattern-syntax](https://github.com/mrmlnc/fast-glob#pattern-syntax).
|
||
Glob can only be a `string`.
|
||
|
||
> ⚠️ 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.
|
||
> On Windows, the forward slash and the backward slash are both separators.
|
||
> Instead please use `/`.
|
||
|
||
**webpack.config.js**
|
||
|
||
```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 windows`
|
||
|
||
If you define `from` as absolute file path or absolute folder path on `Windows`, you can use windows path segment (`\\`)
|
||
|
||
```js
|
||
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](https://github.com/mrmlnc/fast-glob#how-to-write-patterns-on-windows).
|
||
|
||
```js
|
||
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`](#examples)
|
||
|
||
#### `to`
|
||
|
||
Type:
|
||
|
||
```ts
|
||
type to =
|
||
| string
|
||
| ((pathData: { context: string; absoluteFilename?: string }) => string);
|
||
```
|
||
|
||
Default: `compiler.options.output`
|
||
|
||
##### `string`
|
||
|
||
Output path.
|
||
|
||
> ⚠️ 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.
|
||
> On Windows, the forward slash and the backward slash are both separators.
|
||
> Instead please use `/` or `path` methods.
|
||
|
||
**webpack.config.js**
|
||
|
||
```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]",
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
##### `function`
|
||
|
||
Allows to modify the writing path.
|
||
|
||
> ⚠️ 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.
|
||
> On Windows, the forward slash and the backward slash are both separators.
|
||
> Instead please use `/` or `path` methods.
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "src/*.png",
|
||
to({ context, absoluteFilename }) {
|
||
return "dest/newPath/[name][ext]";
|
||
},
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "src/*.png",
|
||
to({ context, absoluteFilename }) {
|
||
return Promise.resolve("dest/newPath/[name][ext]");
|
||
},
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
#### `context`
|
||
|
||
Type:
|
||
|
||
```ts
|
||
type context = string;
|
||
```
|
||
|
||
Default: `options.context|compiler.options.context`
|
||
|
||
A path that determines how to interpret the `from` path.
|
||
|
||
> ⚠️ 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.
|
||
> On Windows, the forward slash and the backward slash are both separators.
|
||
> Instead please use `/` or `path` methods.
|
||
|
||
**webpack.config.js**
|
||
|
||
```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`
|
||
|
||
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`](#examples)
|
||
|
||
#### `globOptions`
|
||
|
||
Type:
|
||
|
||
```ts
|
||
type globOptions = import("globby").Options;
|
||
```
|
||
|
||
Default: `undefined`
|
||
|
||
Allows to configure the glob pattern matching library used by the plugin. [See the list of supported options][glob-options]
|
||
To exclude files from the selection, you should use [globOptions.ignore option](https://github.com/mrmlnc/fast-glob#ignore)
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "public/**/*",
|
||
globOptions: {
|
||
dot: true,
|
||
gitignore: true,
|
||
ignore: ["**/file.*", "**/ignored-directory/**"],
|
||
},
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
#### `filter`
|
||
|
||
Type:
|
||
|
||
```ts
|
||
type filter = (filepath: string) => boolean;
|
||
```
|
||
|
||
Default: `undefined`
|
||
|
||
> ℹ️ To ignore files by path please use the [`globOptions.ignore`](#globoptions) option.
|
||
|
||
**webpack.config.js**
|
||
|
||
```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;
|
||
},
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
#### `toType`
|
||
|
||
Type:
|
||
|
||
```ts
|
||
type toType = "dir" | "file" | "template";
|
||
```
|
||
|
||
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 |
|
||
| :---------------------------: | :------: | :---------: | :--------------------------------------------------------------------------------------------------- |
|
||
| **[`'dir'`](#dir)** | `string` | `undefined` | If `to` has no extension or ends on `'/'` |
|
||
| **[`'file'`](#file)** | `string` | `undefined` | If `to` is not a directory and is not a template |
|
||
| **[`'template'`](#template)** | `string` | `undefined` | If `to` contains [a template pattern](https://webpack.js.org/configuration/output/#template-strings) |
|
||
|
||
##### `'dir'`
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "path/to/file.txt",
|
||
to: "directory/with/extension.ext",
|
||
toType: "dir",
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
##### `'file'`
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "path/to/file.txt",
|
||
to: "file/without/extension",
|
||
toType: "file",
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
##### `'template'`
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "src/",
|
||
to: "dest/[name].[contenthash][ext]",
|
||
toType: "template",
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
#### `force`
|
||
|
||
Type:
|
||
|
||
```ts
|
||
type force = boolean;
|
||
```
|
||
|
||
Default: `false`
|
||
|
||
Overwrites files already in `compilation.assets` (usually added by other plugins/loaders).
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "src/**/*",
|
||
to: "dest/",
|
||
force: true,
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
#### `priority`
|
||
|
||
Type:
|
||
|
||
```ts
|
||
type priority = number;
|
||
```
|
||
|
||
Default: `0`
|
||
|
||
Allows to specify the priority of copying files with the same destination name.
|
||
Files for patterns with higher priority will be copied later.
|
||
To overwrite files, the [`force`](#force) option must be enabled.
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
// Copied second and will overwrite "dir_2/file.txt"
|
||
{
|
||
from: "dir_1/file.txt",
|
||
to: "newfile.txt",
|
||
force: true,
|
||
priority: 10,
|
||
},
|
||
// Copied first
|
||
{
|
||
from: "dir_2/file.txt",
|
||
to: "newfile.txt",
|
||
priority: 5,
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
#### `transform`
|
||
|
||
Type:
|
||
|
||
```ts
|
||
type transform =
|
||
| {
|
||
transformer: (input: string, absoluteFilename: string) => string | Buffer;
|
||
cache?: boolean | TransformerCacheObject | undefined;
|
||
}
|
||
| ((input: string, absoluteFilename: string) => string | Buffer);
|
||
```
|
||
|
||
Default: `undefined`
|
||
|
||
Allows to modify the file contents.
|
||
|
||
##### `function`
|
||
|
||
**webpack.config.js**
|
||
|
||
```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);
|
||
},
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
##### `object`
|
||
|
||
| Name | Default | Description |
|
||
| :-------------------------------: | :---------: | :--------------------------------------------------------------------------------------------------------------- |
|
||
| **[`transformer`](#transformer)** | `undefined` | Allows to modify the file contents. |
|
||
| **[`cache`](#cache)** | `false` | Enable `transform` caching. You can use `transform: { cache: { key: 'my-cache-key' } }` to invalidate the cache. |
|
||
|
||
###### `transformer`
|
||
|
||
Type:
|
||
|
||
```ts
|
||
type transformer = (input: string, absoluteFilename: string) => string;
|
||
```
|
||
|
||
Default: `undefined`
|
||
|
||
**webpack.config.js**
|
||
|
||
```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: {
|
||
transformer(content, absoluteFrom) {
|
||
return optimize(content);
|
||
},
|
||
},
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "src/*.png",
|
||
to: "dest/",
|
||
transform: {
|
||
transformer(content, path) {
|
||
return Promise.resolve(optimize(content));
|
||
},
|
||
},
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
###### `cache`
|
||
|
||
Type:
|
||
|
||
```ts
|
||
type cache =
|
||
| boolean
|
||
| {
|
||
keys: {
|
||
[key: string]: any;
|
||
};
|
||
}
|
||
| {
|
||
keys: (
|
||
defaultCacheKeys: {
|
||
[key: string]: any;
|
||
},
|
||
absoluteFilename: string
|
||
) => Promise<{
|
||
[key: string]: any;
|
||
}>;
|
||
}
|
||
| undefined;
|
||
```
|
||
|
||
Default: `false`
|
||
|
||
**webpack.config.js**
|
||
|
||
Enable/disable and configure caching.
|
||
Default path to cache directory: `node_modules/.cache/copy-webpack-plugin`.
|
||
|
||
###### `boolean`
|
||
|
||
Enables/Disable `transform` caching.
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "src/*.png",
|
||
to: "dest/",
|
||
transform: {
|
||
transformer(content, path) {
|
||
return optimize(content);
|
||
},
|
||
cache: true,
|
||
},
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
##### `object`
|
||
|
||
Enables `transform` caching and setup cache directory and invalidation keys.
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "src/*.png",
|
||
to: "dest/",
|
||
transform: {
|
||
transformer(content, path) {
|
||
return optimize(content);
|
||
},
|
||
cache: {
|
||
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**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "src/*.png",
|
||
to: "dest/",
|
||
transform: {
|
||
transformer(content, path) {
|
||
return optimize(content);
|
||
},
|
||
cache: {
|
||
directory: path.resolve(__dirname, "cache-directory"),
|
||
keys: (defaultCacheKeys, absoluteFrom) => {
|
||
const keys = getCustomCacheInvalidationKeysSync();
|
||
|
||
return {
|
||
...defaultCacheKeys,
|
||
keys,
|
||
};
|
||
},
|
||
},
|
||
},
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
Async function:
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "src/*.png",
|
||
to: "dest/",
|
||
transform: {
|
||
transformer(content, path) {
|
||
return optimize(content);
|
||
},
|
||
cache: {
|
||
directory: path.resolve(__dirname, "cache-directory"),
|
||
keys: async (defaultCacheKeys, absoluteFrom) => {
|
||
const keys = await getCustomCacheInvalidationKeysAsync();
|
||
|
||
return {
|
||
...defaultCacheKeys,
|
||
keys,
|
||
};
|
||
},
|
||
},
|
||
},
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
#### `transformAll`
|
||
|
||
Type:
|
||
|
||
```ts
|
||
type transformAll = (
|
||
data: {
|
||
data: Buffer;
|
||
sourceFilename: string;
|
||
absoluteFilename: string;
|
||
}[]
|
||
) => any;
|
||
```
|
||
|
||
Default: `undefined`
|
||
|
||
Allows you to modify the contents of multiple files and save the result to one file.
|
||
|
||
> ℹ️ The `to` option must be specified and point to a file. It is allowed to use only `[contenthash]` and `[fullhash]` template strings.
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "src/**/*.txt",
|
||
to: "dest/file.txt",
|
||
// The `assets` argument is an assets array for the pattern.from ("src/**/*.txt")
|
||
transformAll(assets) {
|
||
const result = assets.reduce((accumulator, asset) => {
|
||
// The asset content can be obtained from `asset.source` using `source` method.
|
||
// 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()`
|
||
const content = asset.data;
|
||
|
||
accumulator = `${accumulator}${content}\n`;
|
||
return accumulator;
|
||
}, "");
|
||
|
||
return result;
|
||
},
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
### `noErrorOnMissing`
|
||
|
||
Type:
|
||
|
||
```ts
|
||
type noErrorOnMissing = boolean;
|
||
```
|
||
|
||
Default: `false`
|
||
|
||
Doesn't generate an error on missing file(s).
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: path.resolve(__dirname, "missing-file.txt"),
|
||
noErrorOnMissing: true,
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
#### `info`
|
||
|
||
Type:
|
||
|
||
```ts
|
||
type info =
|
||
| Record<string, any>
|
||
| ((item: {
|
||
absoluteFilename: string;
|
||
sourceFilename: string;
|
||
filename: string;
|
||
toType: ToType;
|
||
}) => Record<string, any>);
|
||
```
|
||
|
||
Default: `undefined`
|
||
|
||
Allows to add assets info.
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
"relative/path/to/file.ext",
|
||
{
|
||
from: "**/*",
|
||
// Terser skip this file for minimization
|
||
info: { minimized: true },
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
"relative/path/to/file.ext",
|
||
{
|
||
from: "**/*",
|
||
// Terser skip this file for minimization
|
||
info: (file) => ({ minimized: true }),
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
### Options
|
||
|
||
- [`concurrency`](#concurrency)
|
||
|
||
#### `concurrency`
|
||
|
||
type:
|
||
|
||
```ts
|
||
type concurrency = number;
|
||
```
|
||
|
||
default: `100`
|
||
|
||
limits the number of simultaneous requests to fs
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [...patterns],
|
||
options: { concurrency: 50 },
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
### Examples
|
||
|
||
#### Different variants `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
|
||
```
|
||
|
||
##### From is a Glob
|
||
|
||
Everything that you specify in `from` will be included in the result:
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "src/directory-nested/**/*",
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
Result:
|
||
|
||
```txt
|
||
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**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "**/*",
|
||
context: path.resolve(__dirname, "src", "directory-nested"),
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
Result:
|
||
|
||
```txt
|
||
deep-nested/deepnested-file.txt,
|
||
nested-file.txt
|
||
```
|
||
|
||
##### From is a Dir
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: path.resolve(__dirname, "src", "directory-nested"),
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
Result:
|
||
|
||
```txt
|
||
deep-nested/deepnested-file.txt,
|
||
nested-file.txt
|
||
```
|
||
|
||
Technically, this is `**/*` with a predefined context equal to the specified directory.
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "**/*",
|
||
context: path.resolve(__dirname, "src", "directory-nested"),
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
Result:
|
||
|
||
```txt
|
||
deep-nested/deepnested-file.txt,
|
||
nested-file.txt
|
||
```
|
||
|
||
##### From is a File
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: path.resolve(
|
||
__dirname,
|
||
"src",
|
||
"directory-nested",
|
||
"nested-file.txt"
|
||
),
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
Result:
|
||
|
||
```txt
|
||
nested-file.txt
|
||
```
|
||
|
||
Technically, this is a filename with a predefined context equal to `path.dirname(pathToFile)`.
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "nested-file.txt",
|
||
context: path.resolve(__dirname, "src", "directory-nested"),
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
Result:
|
||
|
||
```txt
|
||
nested-file.txt
|
||
```
|
||
|
||
#### Ignoring files
|
||
|
||
**webpack.config.js**
|
||
|
||
```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/**",
|
||
],
|
||
},
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
#### Flatten copy
|
||
|
||
Removes all directory references and only copies file names.
|
||
|
||
> ⚠️ If files have the same name, the result is non-deterministic.
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: "src/**/*",
|
||
to: "[name][ext]",
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
Result:
|
||
|
||
```txt
|
||
file-1.txt
|
||
file-2.txt
|
||
nested-file.txt
|
||
```
|
||
|
||
#### Copy in new directory
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
// When copying files starting with a dot, must specify the toType option
|
||
// toType: "file",
|
||
to({ context, absoluteFilename }) {
|
||
return `newdirectory/${path.relative(context, absoluteFilename)}`;
|
||
},
|
||
from: "directory",
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
Result:
|
||
|
||
```txt
|
||
"newdirectory/file-1.txt",
|
||
"newdirectory/nestedfile.txt",
|
||
"newdirectory/nested/deep-nested/deepnested.txt",
|
||
"newdirectory/nested/nestedfile.txt",
|
||
```
|
||
|
||
#### Skip running JavaScript files through a minimizer
|
||
|
||
Useful if you need to simply copy `*.js` files to destination "as is" without evaluating and minimizing them using Terser.
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
"relative/path/to/file.ext",
|
||
{
|
||
from: "**/*",
|
||
// Terser skip this file for minimization
|
||
info: { minimized: true },
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
##### `yarn workspaces` and `monorepos`
|
||
|
||
When using `yarn workspaces` or` monorepos`, relative copy paths from node_modules can be broken due to the way packages are hoisting.
|
||
To avoid this, should explicitly specify where to copy the files from using `require.resolve`.
|
||
|
||
**webpack.config.js**
|
||
|
||
```js
|
||
module.exports = {
|
||
plugins: [
|
||
new CopyPlugin({
|
||
patterns: [
|
||
{
|
||
from: `${path.dirname(
|
||
require.resolve(`${moduleName}/package.json`)
|
||
)}/target`,
|
||
to: "target",
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
};
|
||
```
|
||
|
||
## Contributing
|
||
|
||
Please take a moment to read our contributing guidelines if you haven't yet done so.
|
||
|
||
[CONTRIBUTING](./.github/CONTRIBUTING.md)
|
||
|
||
## License
|
||
|
||
[MIT](./LICENSE)
|
||
|
||
[npm]: https://img.shields.io/npm/v/copy-webpack-plugin.svg
|
||
[npm-url]: https://npmjs.com/package/copy-webpack-plugin
|
||
[node]: https://img.shields.io/node/v/copy-webpack-plugin.svg
|
||
[node-url]: https://nodejs.org
|
||
[deps]: https://david-dm.org/webpack-contrib/copy-webpack-plugin.svg
|
||
[deps-url]: https://david-dm.org/webpack-contrib/copy-webpack-plugin
|
||
[tests]: https://github.com/webpack-contrib/copy-webpack-plugin/workflows/copy-webpack-plugin/badge.svg
|
||
[tests-url]: https://github.com/webpack-contrib/copy-webpack-plugin/actions
|
||
[cover]: https://codecov.io/gh/webpack-contrib/copy-webpack-plugin/branch/master/graph/badge.svg
|
||
[cover-url]: https://codecov.io/gh/webpack-contrib/copy-webpack-plugin
|
||
[chat]: https://img.shields.io/badge/gitter-webpack%2Fwebpack-brightgreen.svg
|
||
[chat-url]: https://gitter.im/webpack/webpack
|
||
[size]: https://packagephobia.now.sh/badge?p=copy-webpack-plugin
|
||
[size-url]: https://packagephobia.now.sh/result?p=copy-webpack-plugin
|
||
[glob-options]: https://github.com/sindresorhus/globby#options
|