CopyWebpackPlugin

免責聲明: CopyWebpackPlugin 是由社群成員維護的第三方套件,它可能沒有與 webpack 相同的支援、安全政策或授權,且它並非由 webpack 維護。

npm node tests cover discussion size

將已存在的個別檔案或整個目錄複製到建置目錄。

開始使用

首先,您需要安裝 copy-webpack-plugin

npm install copy-webpack-plugin --save-dev

yarn add -D copy-webpack-plugin

pnpm add -D copy-webpack-plugin

然後將外掛程式新增到您的 webpack 組態。例如

webpack.config.js

const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        { from: "source", to: "dest" },
        { from: "other", to: "public" },
      ],
    }),
  ],
};

注意

copy-webpack-plugin 並非設計為複製建置程序產生的檔案;而是複製建置程序中已存在於原始碼樹中的檔案。

注意

如果您希望 webpack-dev-server 在開發期間將檔案寫入輸出目錄,您可以使用 writeToDisk 選項或 write-file-webpack-plugin 強制執行。

注意

您可以從 資產物件 取得原始來源檔名。

選項

外掛程式簽章

webpack.config.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,
      },
    }),
  ],
};

模式

類型

type from = string;

預設值:未定義

Glob 或路徑,用於複製檔案。Glob 接受 fast-glob 模式語法。Glob 只能是 字串

警告

如果 from 選項是 glob(例如 path\to\file.ext)選項,請勿直接在其中使用 \\,因為在 UNIX 中,反斜線是路徑組成部分中的有效字元,也就是說,它不是分隔符號。在 Windows 中,正斜線和反斜線都是分隔符號。請改用 /

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",
        ),
      ],
    }),
  ],
};
適用於 Windows

如果您在 Windows 中將 from 定義為絕對檔案路徑或絕對資料夾路徑,則可以使用 Windows 路徑區段(\\

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, "file.txt"),
        },
      ],
    }),
  ],
};

但您應始終在 glob 表達式中使用正斜線。請參閱 fast-glob 手冊

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",
          ),
        },
      ],
    }),
  ],
};

context 的行為會根據 from 的內容(globfiledir)而有所不同。更多 範例

類型

type to =
  | string
  | ((pathData: { context: string; absoluteFilename?: string }) => string);

預設值:compiler.options.output

字串

輸出路徑。

警告

請勿在 to(例如 path\to\dest)選項中直接使用 \\,因為在 UNIX 中,反斜線是路徑組件中的一個有效字元,也就是說,它不是一個分隔符號。在 Windows 中,正斜線和反斜線都是分隔符號。請改用 /path 方法。

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]",
        },
      ],
    }),
  ],
};
function

允許修改寫入路徑。

警告

請勿在 to(例如 path\to\newFile)選項中直接傳回 \\,因為在 UNIX 中,反斜線是路徑組件中的一個有效字元,也就是說,它不是一個分隔符號。在 Windows 中,正斜線和反斜線都是分隔符號。請改用 /path 方法。

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to({ context, absoluteFilename }) {
            return "dest/newPath/[name][ext]";
          },
        },
      ],
    }),
  ],
};

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to({ context, absoluteFilename }) {
            return Promise.resolve("dest/newPath/[name][ext]");
          },
        },
      ],
    }),
  ],
};

context

類型

type context = string;

預設值:options.context|compiler.options.context

一個路徑,將(1)加到 from 之前,並(2)從結果路徑的開頭移除。

警告

請勿在 context(例如 path\to\context)選項中直接使用 \\,因為在 UNIX 中,反斜線是路徑組件中的一個有效字元,也就是說,它不是一個分隔符號。在 Windows 中,正斜線和反斜線都是分隔符號。請改用 /path 方法。

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.txt",
          to: "dest/",
          context: "app/",
        },
      ],
    }),
  ],
};

context 可以是絕對路徑或相對路徑。如果它是一個相對路徑,那麼它將根據 compiler.options.context 轉換為一個絕對路徑。

只有當 from 包含一個 glob 時,才應該明確設定 context。否則,context 會根據 from 是檔案或目錄自動設定

如果 from 是檔案,則 context 是它的目錄。結果路徑將僅為檔名。

如果 from 是目錄,則 context 等於 from。結果路徑將是目錄內容(包括巢狀內容)相對於目錄的路徑。

context 的用法說明請參閱這些 範例

globOptions

類型

type globOptions = import("globby").Options;

預設值:未定義

允許設定外掛程式所使用的 glob 模式比對函式庫。 請參閱支援選項清單 若要從選取中排除檔案,您應該使用 globOptions.ignore 選項

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "public/**/*",
          globOptions: {
            dot: true,
            gitignore: true,
            ignore: ["**/file.*", "**/ignored-directory/**"],
          },
        },
      ],
    }),
  ],
};

filter

類型

type filter = (filepath: string) => boolean;

預設值:未定義

注意

若要依路徑忽略檔案,請使用 globOptions.ignore 選項。

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;
          },
        },
      ],
    }),
  ],
};

toType

類型

type toType = "dir" | "file" | "template";

預設值:未定義

決定 to 選項是什麼 - 目錄、檔案或範本。有時很難說 to 是什麼,例如 path/to/dir-with.ext。如果您想複製目錄中的檔案,您需要使用 dir 選項。我們會嘗試自動判斷 type,因此您很可能不需要這個選項。

名稱類型預設值說明
'dir'字串未定義如果 to 沒有副檔名或以 '/' 結尾
'file'字串未定義如果 to 不是目錄也不是範本
'template'字串未定義如果 to 包含 範本模式
'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].[contenthash][ext]",
          toType: "template",
        },
      ],
    }),
  ],
};

force

類型

type force = boolean;

預設值:false

覆寫已在 compilation.assets 中的檔案(通常由其他外掛程式/載入器新增)。

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/**/*",
          to: "dest/",
          force: true,
        },
      ],
    }),
  ],
};

priority

類型

type priority = number;

預設值:0

允許指定具有相同目的地名稱的檔案的複製優先順序。優先順序較高的樣式的檔案將會較晚複製。若要覆寫檔案,必須啟用 force 選項。

webpack.config.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 transform =
  | {
      transformer: (input: string, absoluteFilename: string) => string | Buffer;
      cache?: boolean | TransformerCacheObject | undefined;
    }
  | ((input: string, absoluteFilename: string) => string | Buffer);

預設值:未定義

允許修改檔案內容。

function

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to: "dest/",
          // The `content` argument is a [`Buffer`](https://node.dev.org.tw/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
名稱預設值說明
轉換器未定義允許修改檔案內容。
快取false啟用 transform 快取。您可以使用 transform: { cache: { key: 'my-cache-key' } } 來使快取失效。
transformer

類型

type transformer = (input: string, absoluteFilename: string) => string;

預設值:未定義

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to: "dest/",
          // The `content` argument is a [`Buffer`](https://node.dev.org.tw/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

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to: "dest/",
          transform: {
            transformer(content, path) {
              return Promise.resolve(optimize(content));
            },
          },
        },
      ],
    }),
  ],
};
cache

類型

type cache =
  | boolean
  | {
      keys: {
        [key: string]: any;
      };
    }
  | {
      keys: (
        defaultCacheKeys: {
          [key: string]: any;
        },
        absoluteFilename: string,
      ) => Promise<{
        [key: string]: any;
      }>;
    }
  | undefined;

預設值:false

webpack.config.js

啟用/停用快取並設定快取。快取目錄的預設路徑:node_modules/.cache/copy-webpack-plugin

boolean

啟用/停用 transform 快取。

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to: "dest/",
          transform: {
            transformer(content, path) {
              return optimize(content);
            },
            cache: true,
          },
        },
      ],
    }),
  ],
};
object

啟用 transform 快取並設定失效金鑰。

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to: "dest/",
          transform: {
            transformer(content, path) {
              return optimize(content);
            },
            cache: {
              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",
              },
            },
          },
        },
      ],
    }),
  ],
};

您可以使用函式設定失效金鑰。

簡單函式

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to: "dest/",
          transform: {
            transformer(content, path) {
              return optimize(content);
            },
            cache: {
              keys: (defaultCacheKeys, absoluteFrom) => {
                const keys = getCustomCacheInvalidationKeysSync();

                return {
                  ...defaultCacheKeys,
                  keys,
                };
              },
            },
          },
        },
      ],
    }),
  ],
};

非同步函式

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to: "dest/",
          transform: {
            transformer(content, path) {
              return optimize(content);
            },
            cache: {
              keys: async (defaultCacheKeys, absoluteFrom) => {
                const keys = await getCustomCacheInvalidationKeysAsync();

                return {
                  ...defaultCacheKeys,
                  keys,
                };
              },
            },
          },
        },
      ],
    }),
  ],
};

transformAll

類型

type transformAll = (
  data: {
    data: Buffer;
    sourceFilename: string;
    absoluteFilename: string;
  }[],
) => any;

預設值:未定義

允許您修改多個檔案的內容,並將結果儲存到一個檔案。

注意

to 選項必須指定,並指向一個檔案。允許僅使用 [contenthash][fullhash] 範本字串。

webpack.config.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://node.dev.org.tw/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 noErrorOnMissing = boolean;

預設值:false

在缺少檔案時不會產生錯誤。

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, "missing-file.txt"),
          noErrorOnMissing: true,
        },
      ],
    }),
  ],
};

info

類型

type info =
  | Record<string, any>
  | ((item: {
      absoluteFilename: string;
      sourceFilename: string;
      filename: string;
      toType: ToType;
    }) => Record<string, any>);

預設值:未定義

允許新增資產資訊。

webpack.config.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

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        "relative/path/to/file.ext",
        {
          from: "**/*",
          // Terser skip this file for minimization
          info: (file) => ({ minimized: true }),
        },
      ],
    }),
  ],
};

選項

concurrency

類型

type concurrency = number;

預設值:100

限制同時對 fs 提出請求的數量

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [...patterns],
      options: { concurrency: 50 },
    }),
  ],
};

範例

from 的不同變體(globfiledir)。

例如,以下檔案結構

src/directory-nested/deep-nested/deepnested-file.txt
src/directory-nested/nested-file.txt
From 是 Glob

您在 from 中指定的任何內容都將包含在結果中

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/directory-nested/**/*",
        },
      ],
    }),
  ],
};

結果

src/directory-nested/deep-nested/deepnested-file.txt,
src/directory-nested/nested-file.txt

如果您不希望結果路徑以 src/directory-nested/ 開頭,則應將 src/directory-nested/ 移至 context,這樣 from 中只會保留 glob 模式 **/*

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "**/*",
          context: path.resolve(__dirname, "src", "directory-nested"),
        },
      ],
    }),
  ],
};

結果

deep-nested/deepnested-file.txt,
nested-file.txt
From 是 Dir

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, "src", "directory-nested"),
        },
      ],
    }),
  ],
};

結果

deep-nested/deepnested-file.txt,
nested-file.txt

技術上來說,這是 **/*,預先定義的 context 等於指定的目錄。

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "**/*",
          context: path.resolve(__dirname, "src", "directory-nested"),
        },
      ],
    }),
  ],
};

結果

deep-nested/deepnested-file.txt,
nested-file.txt
From 是 File
module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(
            __dirname,
            "src",
            "directory-nested",
            "nested-file.txt",
          ),
        },
      ],
    }),
  ],
};

結果

nested-file.txt

技術上來說,這是一個檔名,預先定義的 context 等於 path.dirname(pathToFile)

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "nested-file.txt",
          context: path.resolve(__dirname, "src", "directory-nested"),
        },
      ],
    }),
  ],
};

結果

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/**",
            ],
          },
        },
      ],
    }),
  ],
};

扁平化複製

移除所有目錄參考,只複製檔案名稱。

警告

如果檔案名稱相同,結果將是非確定性的。

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/**/*",
          to: "[name][ext]",
        },
      ],
    }),
  ],
};

結果

file-1.txt
file-2.txt
nested-file.txt

複製到新目錄

webpack.config.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",
        },
      ],
    }),
  ],
};

結果

"newdirectory/file-1.txt",
"newdirectory/nestedfile.txt",
"newdirectory/nested/deep-nested/deepnested.txt",
"newdirectory/nested/nestedfile.txt",

略過使用壓縮器執行 JavaScript 檔案

如果你需要將 *.js 檔案「原樣」複製到目的地,而不需要使用 Terser 評估和壓縮它們,這會很有用。

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        "relative/path/to/file.ext",
        {
          from: "**/*",
          // Terser skip this file for minimization
          info: { minimized: true },
        },
      ],
    }),
  ],
};
yarn workspacesmonorepos

在使用 yarn workspacesmonorepos 時,由於套件的提升方式,來自 node_modules 的相對複製路徑可能會中斷。為避免此問題,應明確指定從何處複製檔案,方法是使用 require.resolve

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: `${path.dirname(
            require.resolve(`${moduleName}/package.json`),
          )}/target`,
          to: "target",
        },
      ],
    }),
  ],
};

貢獻

如果你尚未閱讀我們的貢獻指南,請花點時間閱讀。

貢獻指南

授權

MIT