TerserWebpackPlugin

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

npm node tests cover discussion size

此外掛使用 terser 來最小化/簡化您的 JavaScript。

入門

Webpack v5 內建最新的 terser-webpack-plugin。如果您使用的是 Webpack v5 或以上版本,且想要自訂選項,您仍然需要安裝 terser-webpack-plugin。使用 Webpack v4,您必須安裝 terser-webpack-plugin v4。

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

npm install terser-webpack-plugin --save-dev

yarn add -D terser-webpack-plugin

pnpm add -D terser-webpack-plugin

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

webpack.config.js

const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [new TerserPlugin()],
  },
};

並透過您偏好的方式執行 webpack

關於原始碼對應的注意事項

僅適用於 devtool 選項的 source-mapinline-source-maphidden-source-mapnosources-source-map 值。

原因:

  • eval 會將模組包裝在 eval("string") 中,而縮小器無法處理字串。
  • cheap 沒有欄位資訊,而縮小器只會產生單一行,只留下單一對應。

使用支援的 devtool 值可啟用原始碼對應產生。

選項

test

類型

type test = string | RegExp | Array<string | RegExp>;

預設值:/\.m?js(\?.*)?$/i

用於比對檔案的測試。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        test: /\.js(\?.*)?$/i,
      }),
    ],
  },
};

include

類型

type include = string | RegExp | Array<string | RegExp>;

預設值:undefined

要包含的檔案。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        include: /\/includes/,
      }),
    ],
  },
};

exclude

類型

type exclude = string | RegExp | Array<string | RegExp>;

預設值:undefined

要排除的檔案。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        exclude: /\/excludes/,
      }),
    ],
  },
};

parallel

類型

type parallel = boolean | number;

預設值:true

使用多處理平行執行來提升建置速度。同時執行的預設數量:os.cpus().length - 1

注意

平行化可以大幅提升您的建置速度,因此強烈建議使用。

警告

如果您使用 Circle CI 或任何其他無法提供實際可用 CPU 數量的環境,則需要明確設定 CPU 數量,以避免出現 Error: Call retries were exceeded(請參閱 #143#202)。

布林值

啟用/停用多處理程序並行執行。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: true,
      }),
    ],
  },
};

數字

啟用多處理程序並行執行,並設定並行執行的數量。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: 4,
      }),
    ],
  },
};

最小化

類型

type minify = (
  input: {
    [file: string]: string;
  },
  sourceMap: import("@jridgewell/trace-mapping").SourceMapInput | undefined,
  minifyOptions: {
    module?: boolean | undefined;
    ecma?: import("terser").ECMA | undefined;
  },
  extractComments:
    | boolean
    | "all"
    | "some"
    | RegExp
    | ((
        astNode: any,
        comment: {
          value: string;
          type: "comment1" | "comment2" | "comment3" | "comment4";
          pos: number;
          line: number;
          col: number;
        }
      ) => boolean)
    | {
        condition?:
          | boolean
          | "all"
          | "some"
          | RegExp
          | ((
              astNode: any,
              comment: {
                value: string;
                type: "comment1" | "comment2" | "comment3" | "comment4";
                pos: number;
                line: number;
                col: number;
              }
            ) => boolean)
          | undefined;
        filename?: string | ((fileData: any) => string) | undefined;
        banner?:
          | string
          | boolean
          | ((commentsFile: string) => string)
          | undefined;
      }
    | undefined
) => Promise<{
  code: string;
  map?: import("@jridgewell/trace-mapping").SourceMapInput | undefined;
  errors?: (string | Error)[] | undefined;
  warnings?: (string | Error)[] | undefined;
  extractedComments?: string[] | undefined;
}>;

預設:TerserPlugin.terserMinify

讓您可以覆寫預設的最小化函式。預設情況下,外掛程式會使用 terser 套件。這對於使用和測試未發布的版本或分支很有用。

警告

當啟用 parallel 選項時,請務必在 minify 函式內使用 require.

webpack.config.js

// Can be async
const minify = (input, sourceMap, minimizerOptions, extractsComments) => {
  // The `minimizerOptions` option contains option from the `terserOptions` option
  // You can use `minimizerOptions.myCustomOption`

  // Custom logic for extract comments
  const { map, code } = require("uglify-module") // Or require('./path/to/uglify-module')
    .minify(input, {
      /* Your options for minification */
    });

  return { map, code, warnings: [], errors: [], extractedComments: [] };
};

// Used to regenerate `fullhash`/`chunkhash` between different implementation
// Example: you fix a bug in custom minimizer/custom function, but unfortunately webpack doesn't know about it, so you will get the same fullhash/chunkhash
// to avoid this you can provide version of your custom minimizer
// You don't need if you use only `contenthash`
minify.getMinimizerVersion = () => {
  let packageJson;

  try {
    // eslint-disable-next-line global-require, import/no-extraneous-dependencies
    packageJson = require("uglify-module/package.json");
  } catch (error) {
    // Ignore
  }

  return packageJson && packageJson.version;
};

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          myCustomOption: true,
        },
        minify,
      }),
    ],
  },
};

terserOptions

類型

type terserOptions = {
  compress?: boolean | CompressOptions;
  ecma?: ECMA;
  enclose?: boolean | string;
  ie8?: boolean;
  keep_classnames?: boolean | RegExp;
  keep_fnames?: boolean | RegExp;
  mangle?: boolean | MangleOptions;
  module?: boolean;
  nameCache?: object;
  format?: FormatOptions;
  /** @deprecated */
  output?: FormatOptions;
  parse?: ParseOptions;
  safari10?: boolean;
  sourceMap?: boolean | SourceMapOptions;
  toplevel?: boolean;
};

預設:預設

Terser 選項

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          ecma: undefined,
          parse: {},
          compress: {},
          mangle: true, // Note `mangle.properties` is `false` by default.
          module: false,
          // Deprecated
          output: null,
          format: null,
          toplevel: false,
          nameCache: null,
          ie8: false,
          keep_classnames: undefined,
          keep_fnames: false,
          safari10: false,
        },
      }),
    ],
  },
};

extractComments

類型

type extractComments =
  | boolean
  | string
  | RegExp
  | ((
      astNode: any,
      comment: {
        value: string;
        type: "comment1" | "comment2" | "comment3" | "comment4";
        pos: number;
        line: number;
        col: number;
      }
    ) => boolean)
  | {
      condition?:
        | boolean
        | "all"
        | "some"
        | RegExp
        | ((
            astNode: any,
            comment: {
              value: string;
              type: "comment1" | "comment2" | "comment3" | "comment4";
              pos: number;
              line: number;
              col: number;
            }
          ) => boolean)
        | undefined;
      filename?: string | ((fileData: any) => string) | undefined;
      banner?:
        | string
        | boolean
        | ((commentsFile: string) => string)
        | undefined;
    };

預設值:true

是否將註解萃取到一個獨立的檔案中(請參閱 詳細資訊)。預設情況下,僅萃取使用 /^\**!|@preserve|@license|@cc_on/i 正規表示式條件的註解,並移除其餘的註解。如果原始檔案的名稱為 foo.js,則註解將儲存在 foo.js.LICENSE.txt 中。terserOptions.format.comments 選項指定是否保留註解,亦即有可能在萃取其他註解或甚至保留已萃取的註解時,保留某些註解(例如註釋)。

布林值

啟用/停用萃取註解。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: true,
      }),
    ],
  },
};

字串

擷取全部部分(使用 /^\**!|@preserve|@license|@cc_on/i RegExp)註解。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: "all",
      }),
    ],
  },
};

RegExp

所有符合給定表達式的註解都將擷取到個別檔案中。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: /@extract/i,
      }),
    ],
  },
};

function

所有符合給定表達式的註解都將擷取到個別檔案中。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: (astNode, comment) => {
          if (/@extract/i.test(comment.value)) {
            return true;
          }

          return false;
        },
      }),
    ],
  },
};

object

允許自訂擷取註解的條件,指定擷取的檔案名稱和標題。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: {
          condition: /^\**!|@preserve|@license|@cc_on/i,
          filename: (fileData) => {
            // The "fileData" argument contains object with "filename", "basename", "query" and "hash"
            return `${fileData.filename}.LICENSE.txt${fileData.query}`;
          },
          banner: (licenseFile) => {
            return `License information can be found in ${licenseFile}`;
          },
        },
      }),
    ],
  },
};
condition

類型

type condition =
  | boolean
  | "all"
  | "some"
  | RegExp
  | ((
      astNode: any,
      comment: {
        value: string;
        type: "comment1" | "comment2" | "comment3" | "comment4";
        pos: number;
        line: number;
        col: number;
      }
    ) => boolean)
  | undefined;

您需要擷取的註解條件。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: {
          condition: "some",
          filename: (fileData) => {
            // The "fileData" argument contains object with "filename", "basename", "query" and "hash"
            return `${fileData.filename}.LICENSE.txt${fileData.query}`;
          },
          banner: (licenseFile) => {
            return `License information can be found in ${licenseFile}`;
          },
        },
      }),
    ],
  },
};
filename

類型

type filename = string | ((fileData: any) => string) | undefined;

預設值:[file].LICENSE.txt[query]

可用的佔位符:[file][query][filebase](Webpack 5 為 [base])。

將擷取的註解儲存到的檔案。預設值是將字尾 .LICENSE.txt 附加到原始檔名。

警告

我們強烈建議使用 txt 副檔名。使用 js/cjs/mjs 副檔名可能會與現有資產衝突,導致程式碼中斷。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: {
          condition: /^\**!|@preserve|@license|@cc_on/i,
          filename: "extracted-comments.js",
          banner: (licenseFile) => {
            return `License information can be found in ${licenseFile}`;
          },
        },
      }),
    ],
  },
};
banner

類型

type banner = string | boolean | ((commentsFile: string) => string) | undefined;

預設值:/*! 如需授權資訊,請參閱 ${commentsFile} */

指向提取檔案的橫幅文字,且會新增在原始檔案的頂端。可以是 false(無橫幅)、字串Function<(字串) -> 字串>,後者會以儲存提取註解之檔案名稱為參數呼叫。會包裝成註解。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: {
          condition: true,
          filename: (fileData) => {
            // The "fileData" argument contains object with "filename", "basename", "query" and "hash"
            return `${fileData.filename}.LICENSE.txt${fileData.query}`;
          },
          banner: (commentsFile) => {
            return `My custom banner about license information ${commentsFile}`;
          },
        },
      }),
    ],
  },
};

範例

保留註解

提取所有合法的註解(例如 /^\**!|@preserve|@license|@cc_on/i),並保留 /@license/i 註解。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          format: {
            comments: /@license/i,
          },
        },
        extractComments: true,
      }),
    ],
  },
};

移除註解

如果您避免使用註解進行建置,請使用此設定檔

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          format: {
            comments: false,
          },
        },
        extractComments: false,
      }),
    ],
  },
};

uglify-js

UglifyJS 是一個 JavaScript 解析器、縮小器、壓縮器和美化工具組。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        minify: TerserPlugin.uglifyJsMinify,
        // `terserOptions` options will be passed to `uglify-js`
        // Link to options - https://github.com/mishoo/UglifyJS#minify-options
        terserOptions: {},
      }),
    ],
  },
};

swc

swc 是一個用 Rust 編寫的超快速編譯器;從現代標準和 TypeScript 產生廣泛支援的 JavaScript。

警告

extractComments 選項不受支援,且預設會移除所有註解,此問題將在未來修正

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        minify: TerserPlugin.swcMinify,
        // `terserOptions` options will be passed to `swc` (`@swc/core`)
        // Link to options - https://swc.dev.org.tw/docs/config-js-minify
        terserOptions: {},
      }),
    ],
  },
};

esbuild

esbuild 是一個極快的 JavaScript 捆綁器和縮小器。

警告

extractComments 選項不受支援,且會保留所有合法的註解(例如著作權、授權等)

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        minify: TerserPlugin.esbuildMinify,
        // `terserOptions` options will be passed to `esbuild`
        // Link to options - https://esbuild.dev.org.tw/api/#minify
        // Note: the `minify` options is true by default (and override other `minify*` options), so if you want to disable the `minifyIdentifiers` option (or other `minify*` options) please use:
        // terserOptions: {
        //   minify: false,
        //   minifyWhitespace: true,
        //   minifyIdentifiers: false,
        //   minifySyntax: true,
        // },
        terserOptions: {},
      }),
    ],
  },
};

自訂縮小函式

覆寫預設的壓縮函式 - 使用 uglify-js 進行壓縮。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        minify: (file, sourceMap) => {
          // https://github.com/mishoo/UglifyJS2#minify-options
          const uglifyJsOptions = {
            /* your `uglify-js` package options */
          };

          if (sourceMap) {
            uglifyJsOptions.sourceMap = {
              content: sourceMap,
            };
          }

          return require("uglify-js").minify(file, uglifyJsOptions);
        },
      }),
    ],
  },
};

Typescript

使用預設的 terser 壓縮函式

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: true,
        },
      }),
    ],
  },
};

使用內建的壓縮函式

import type { JsMinifyOptions as SwcOptions } from "@swc/core";
import type { MinifyOptions as UglifyJSOptions } from "uglify-js";
import type { TransformOptions as EsbuildOptions } from "esbuild";
import type { MinifyOptions as TerserOptions } from "terser";

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin<SwcOptions>({
        minify: TerserPlugin.swcMinify,
        terserOptions: {
          // `swc` options
        },
      }),
      new TerserPlugin<UglifyJSOptions>({
        minify: TerserPlugin.uglifyJsMinify,
        terserOptions: {
          // `uglif-js` options
        },
      }),
      new TerserPlugin<EsbuildOptions>({
        minify: TerserPlugin.esbuildMinify,
        terserOptions: {
          // `esbuild` options
        },
      }),

      // Alternative usage:
      new TerserPlugin<TerserOptions>({
        minify: TerserPlugin.terserMinify,
        terserOptions: {
          // `terser` options
        },
      }),
    ],
  },
};

貢獻

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

貢獻

授權

MIT