可打印

AutomaticPrefetchPlugin

AutomaticPrefetchPlugin 在观察更改时,会预先发现先前编译中的**所有模块**,以尝试改进增量构建时间。相比之下,PrefetchPlugin 预先发现的是**单个模块**。

webpack.config.js

module.exports = {
  // ...
  plugins: [new webpack.AutomaticPrefetchPlugin()],
};

BannerPlugin

在每个生成的 chunk 顶部添加一个 banner。

const webpack = require('webpack');

new webpack.BannerPlugin(banner);
// or
new webpack.BannerPlugin(options);

选项

{
  banner: string | function, // the banner as string or function, it will be wrapped in a comment
  raw: boolean, // if true, banner will not be wrapped in a comment
  entryOnly: boolean, // if true, the banner will only be added to the entry chunks
  test: string | RegExp | [string, RegExp], // Include all modules that pass test assertion.
  include: string | RegExp | [string, RegExp], // Include all modules matching any of these conditions.
  exclude: string | RegExp | [string, RegExp], // Exclude all modules matching any of these conditions.
  footer?: boolean, // if true, the banner will be placed at the end of the compilation
  stage?: number, // the stage of the compilation in which the banner should be injected
}

用法

import webpack from 'webpack';

// string
new webpack.BannerPlugin({
  banner: 'hello world',
});

// function
new webpack.BannerPlugin({
  banner: (yourVariable) => {
    return `yourVariable: ${yourVariable}`;
  },
});

// It will add the banner message after minimizers and any asset manipulation
new webpack.BannerPlugin({
  raw: true,
  banner: '/* banner is a string */',
  stage: webpack.Compilation.PROCESS_ASSETS_STAGE_REPORT,
});

占位符

从 webpack 2.5.0 开始,占位符在 banner 字符串中进行求值。

import webpack from 'webpack';

new webpack.BannerPlugin({
  banner:
    'fullhash:[fullhash], chunkhash:[chunkhash], name:[name], filebase:[filebase], query:[query], file:[file]',
});

ChunksWebpackPlugin

GitHub Workflow Status (branch) Coverage Status Npm downloads

chunks-webpack-plugin 创建包含入口点和 chunk 关系的 HTML 文件,用于服务你的 webpack bundles。它适用于包含多个入口点的多页面应用程序。

从 webpack 4 开始,SplitChunksPlugin 提供了优化所有 chunk 的可能性。它可能特别强大,因为这意味着 chunk 甚至可以在异步和非异步 chunk 之间共享。有关详细信息,请参阅 webpack 文档中的 splitChunks.chunks

splitChunks.chunks 选项可以设置为自动生成与入口点关联的新 chunk。例如,入口点 a.jsb.js 与文件 vendors~a~b.js 共享通用代码。

在有多个入口点的情况下,识别自动生成的 chunk 和入口点之间的关系可能很困难。

chunks-webpack-plugin 解析 webpack 编译的入口点以获取与入口点关联的所有文件。然后,它生成 HTML 文件,其中包含按入口点筛选的所有资产和 chunks-manifest.json 文件。

零配置

它无需配置即可工作。对于高级用法,请参阅使用配置部分

安装

chunks-webpack-plugin 在 npm 上可用,名称为 chunks-webpack-plugin,在 GitHub 上也可用,名称为 chunks-webpack-plugin

npm install chunks-webpack-plugin --save-dev
yarn add chunks-webpack-plugin --dev

[!WARNING] 插件 chunks-webpack-plugin@10 仅支持 ESM。 [!NOTE] 支持的最低 Node.js 版本为 16.20.0,Webpack 版本为 >=5.10.3

示例

该项目在 ./example 目录中包含一个极简示例。运行 npm run build:example 命令以执行 Webpack 示例并查看插件的实际实现。

基本用法

chunks-webpack-plugin 将为每个入口点生成两个 HTML 文件。每个文件名都包含入口点名称,{{entry}} 占位符会自动替换。

  • {{entry}}-styles.html:包含所有 HTML <link> 标签
  • {{entry}}-scripts.html:包含所有 HTML <script> 标签

首先,将插件添加到 webpack 配置中。

webpack.config.js

import ChunksWebpackPlugin from 'chunks-webpack-plugin';

export default {
  plugins: [new ChunksWebpackPlugin()]
};

HTML 文件与 webpack 编译的其余部分一起构建在输出路径目录中。

现在你可以将生成的 HTML 文件包含到你的 HTML 页面模板中。你可以通过 Twig 等方式实现。

main-styles.html

<link rel="stylesheet" href="main.css" />

main-scripts.html

<script defer src="main.js"></script>

使用配置

你可以向 chunks-webpack-plugin 传递一个配置对象来覆盖默认设置。

filename

类型

type filename = string;

默认值:'[name]-[type].html'

指示插件是否个性化生成文件的文件名。文件由 webpack 编译处理并在输出路径目录中生成。占位符 [name] 会自动替换为入口点名称,[type] 会替换为 styles|scripts

new ChunksWebpackPlugin({
  filename: 'templates/[name]-[type].html'
});

[!NOTE] filename 可以包含目录,这些目录将自动创建。

templateStyle

类型

type templateStyle = (name: string, entryName: string) => string;

默认值

(name) => `<link rel="stylesheet" href="${name}" />`;

指示插件是否个性化 HTML <style> 标签的默认模板。例如,添加额外的属性或 CDN 前缀。

export default {
  plugins: [
    new ChunksWebpackPlugin({
      templateStyle: (name) => `<link rel="stylesheet" href="https://cdn.domain.com${name}" />`
    })
  ]
};

templateScript

类型

type templateScript = (name: string, entryName: string) => string;

默认值

(name) => `<script defer src="${name}"></script>`;

指示插件是否个性化 HTML <script> 标签的默认模板。例如,添加额外的属性或 CDN 前缀。

export default {
  plugins: [
    new ChunksWebpackPlugin({
      templateScript: (name) => `<script defer src="https://cdn.domain.com${name}"></script>`
    })
  ]
};

generateChunksManifest

类型

type generateChunksManifest = boolean;

默认值:false

指示插件是否生成 chunks-manifest.json。该文件包含按入口点分组的所有 chunk 列表。请参阅 chunks-manifest.json 示例

export default {
  plugins: [
    new ChunksWebpackPlugin({
      generateChunksManifest: true
    })
  ]
};

generateChunksFiles

类型

type generateChunksFiles = boolean;

默认值:true

指示插件是否生成 HTML 文件。

export default {
  plugins: [
    new ChunksWebpackPlugin({
      generateChunksFiles: false
    })
  ]
};

[!WARNING] 当设置为 false 时,HTML 文件将不会生成。它generateChunksManifest 选项设置为 true 并用于自定义生成 HTML 文件时才有用。


多入口示例

多入口点示例

使用 splitChunks 选项共享通用代码的多个入口点的 webpack 配置示例。

import ChunksWebpackPlugin from 'chunks-webpack-plugin';
import path from 'node:path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

export default {
  entry: {
    home: 'home.js',
    news: 'news.js'
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, './dist')
  },
  plugins: [new ChunksWebpackPlugin()],
  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  }
};

插件将在输出路径目录中生成所有文件。

home-styles.html

<link rel="stylesheet" href="vendors~home~news.css" />
<link rel="stylesheet" href="home.css" />

home-scripts.html

<script defer src="vendors~home~news.js"></script>
<script defer src="home.js"></script>

news-styles.html

<link rel="stylesheet" href="vendors~home~news.css" />
<link rel="stylesheet" href="news.css" />

news-scripts.html

<script defer src="vendors~home~news.js"></script>
<script defer src="news.js"></script>

许可证

chunks-webpack-plugin 根据 MIT 许可证获得许可。

@yoriiis 用 ♥ 创建。

CommonsChunkPlugin

CommonsChunkPlugin 是一个选择加入的功能,它创建一个单独的文件(称为 chunk),由多个入口点之间共享的通用模块组成。

通过将通用模块从 bundles 中分离出来,生成的 chunked 文件可以最初加载一次,并存储在缓存中供以后使用。这会带来页面速度优化,因为浏览器可以从缓存中快速提供共享代码,而无需在每次访问新页面时都被迫加载更大的 bundle。

new webpack.optimize.CommonsChunkPlugin(options);

选项

{
  name: string, // or
  names: string[],
  // The chunk name of the commons chunk. An existing chunk can be selected by passing a name of an existing chunk.
  // If an array of strings is passed this is equal to invoking the plugin multiple times for each chunk name.
  // If omitted and `options.async` or `options.children` is set all chunks are used, otherwise `options.filename`
  // is used as chunk name.
  // When using `options.async` to create common chunks from other async chunks you must specify an entry-point
  // chunk name here instead of omitting the `option.name`.

  filename: string,
  // The filename template for the commons chunk. Can contain the same placeholders as `output.filename`.
  // If omitted the original filename is not modified (usually `output.filename` or `output.chunkFilename`).
  // This option is not permitted if you're using `options.async` as well, see below for more details.

  minChunks: number|Infinity|function(module, count) => boolean,
  // The minimum number of chunks which need to contain a module before it's moved into the commons chunk.
  // The number must be greater than or equal 2 and lower than or equal to the number of chunks.
  // Passing `Infinity` creates the commons chunk, but moves no modules into it.
  // By providing a `function` you can add custom logic. (Defaults to the number of chunks)

  chunks: string[],
  // Select the source chunks by chunk names. The chunk must be a child of the commons chunk.
  // If omitted all entry chunks are selected.

  children: boolean,
  // If `true` all children of the commons chunk are selected

  deepChildren: boolean,
  // If `true` all descendants of the commons chunk are selected

  async: boolean|string,
  // If `true` a new async commons chunk is created as child of `options.name` and sibling of `options.chunks`.
  // It is loaded in parallel with `options.chunks`.
  // Instead of using `option.filename`, it is possible to change the name of the output file by providing
  // the desired string here instead of `true`.

  minSize: number,
  // Minimum size of all common module before a commons chunk is created.
}

示例

入口点的公共 chunk

生成一个额外的 chunk,其中包含入口点之间共享的通用模块。

new webpack.optimize.CommonsChunkPlugin({
  name: 'commons',
  // (the commons chunk name)

  filename: 'commons.js',
  // (the filename of the commons chunk)

  // minChunks: 3,
  // (Modules must be shared between 3 entries)

  // chunks: ["pageA", "pageB"],
  // (Only use these entries)
});

你必须在入口点之前加载生成的 chunk。

<script src="commons.js" charset="utf-8"></script>
<script src="entry.bundle.js" charset="utf-8"></script>

显式供应商 chunk

将你的代码拆分为供应商和应用程序部分。

module.exports = {
  //...
  entry: {
    vendor: ['jquery', 'other-lib'],
    app: './entry',
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      // filename: "vendor.js"
      // (Give the chunk a different name)

      minChunks: Infinity,
      // (with more entries, this ensures that no other module
      //  goes into the vendor chunk)
    }),
  ],
};
<script src="vendor.js" charset="utf-8"></script>
<script src="app.js" charset="utf-8"></script>

将通用模块移入父 chunk

通过代码分割,入口 chunk 的多个子 chunk 可以拥有共同的依赖。为了防止重复,这些依赖可以移入父 chunk。这会减少总体大小,但会对初始加载时间产生负面影响。如果预计用户需要下载许多兄弟 chunk(即入口 chunk 的子 chunk),那么这应该会总体上改善加载时间。

new webpack.optimize.CommonsChunkPlugin({
  // names: ["app", "subPageA"]
  // (choose the chunks, or omit for all chunks)

  children: true,
  // (select all children of chosen chunks)

  // minChunks: 3,
  // (3 children must share the module before it's moved)
});

额外的异步公共 chunk

与上述类似,但不是将通用模块移入父 chunk(这会增加初始加载时间),而是使用一个新的异步加载的额外通用 chunk。当下载额外的 chunk 时,它会自动并行下载。

new webpack.optimize.CommonsChunkPlugin({
  name: 'app',
  // or
  names: ['app', 'subPageA'],
  // the name or list of names must match the name or names
  // of the entry points that create the async chunks

  children: true,
  // (use all children of the chunk)

  async: true,
  // (create an async commons chunk)

  minChunks: 3,
  // (3 children must share the module before it's separated)
});

将函数传递给 minChunks 属性

你还可以将函数传递给 minChunks 属性。此函数由 CommonsChunkPlugin 调用,并以 modulecount 参数调用该函数。

module 参数表示你通过 name/names 属性提供的 chunk 中的每个模块。module 具有 NormalModule 的形状,其中有两个特别有用的属性适用于此用例:

  • module.context:存储文件的目录。例如:'/my_project/node_modules/example-dependency'
  • module.resource:正在处理的文件名。例如:'/my_project/node_modules/example-dependency/index.js'

count 参数表示 module 在多少个 chunk 中被使用。

当您希望对 CommonsChunk 算法如何确定模块应移动到何处进行细粒度控制时,此选项很有用。

new webpack.optimize.CommonsChunkPlugin({
  name: 'my-single-lib-chunk',
  filename: 'my-single-lib-chunk.js',
  minChunks: function (module, count) {
    // If module has a path, and inside of the path exists the name "somelib",
    // and it is used in 3 separate chunks/entries, then break it out into
    // a separate chunk with chunk keyname "my-single-lib-chunk", and filename "my-single-lib-chunk.js"
    return module.resource && /somelib/.test(module.resource) && count === 3;
  },
});

如上所示,此示例允许你仅在函数内满足所有条件时才将一个库移动到单独的文件中。

此概念可用于获取隐式通用供应商 chunk。

new webpack.optimize.CommonsChunkPlugin({
  name: 'vendor',
  minChunks: function (module) {
    // this assumes your vendor imports exist in the node_modules directory
    return module.context && module.context.includes('node_modules');
  },
});

清单文件

要将 webpack 引导逻辑提取到单独的文件中,请对未定义为 entryname 使用 CommonsChunkPlugin。通常使用名称 manifest。有关详细信息,请参阅缓存指南

new webpack.optimize.CommonsChunkPlugin({
  name: 'manifest',
  minChunks: Infinity,
});

结合隐式通用供应商 chunk 和清单文件

由于 vendormanifest chunk 使用不同的 minChunks 定义,你需要两次调用插件。

[
  new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor',
    minChunks: function (module) {
      return module.context && module.context.includes('node_modules');
    },
  }),
  new webpack.optimize.CommonsChunkPlugin({
    name: 'manifest',
    minChunks: Infinity,
  }),
];

更多示例

CompressionWebpackPlugin

npm node tests cover discussion size

准备资产的压缩版本,以便使用 Content-Encoding 进行服务。

入门

首先,你需要安装 compression-webpack-plugin

npm install compression-webpack-plugin --save-dev

yarn add -D compression-webpack-plugin

pnpm add -D compression-webpack-plugin

然后将插件添加到你的 webpack 配置中。例如:

webpack.config.js

const CompressionPlugin = require("compression-webpack-plugin");

module.exports = {
  plugins: [new CompressionPlugin()],
};

最后,使用你通常使用的方法运行 webpack(例如,通过 CLI 或 npm 脚本)。

选项

test

类型

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

默认值:undefined

包含所有通过测试断言的资产。

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      test: /\.js(\?.*)?$/i,
    }),
  ],
};

include

类型

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

默认值:undefined

包含所有符合这些条件之一的资产。

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      include: /\/includes/,
    }),
  ],
};

exclude

类型

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

默认值:undefined

排除所有符合这些条件之一的资产。

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      exclude: /\/excludes/,
    }),
  ],
};

algorithm

类型

type algorithm =
  | string
  | ((
      input: Buffer,
      options: CompressionOptions,
      callback: (
        error: Error | null | undefined,
        result:
          | string
          | ArrayBuffer
          | SharedArrayBuffer
          | Uint8Array
          | readonly number[]
          | {
              valueOf(): ArrayBuffer | SharedArrayBuffer;
            }
          | {
              valueOf(): string | Uint8Array | readonly number[];
            }
          | {
              valueOf(): string;
            }
          | {
              [Symbol.toPrimitive](hint:%20%22string%22): string;
            },
      ) => void,
    ) => any);

定义要使用的压缩算法或函数。默认为 gzip

[!注意]

如果你为 algorithm 选项使用自定义函数,则 compressionOptions 的默认值将为空对象 {}

string

该算法基于 Node.js zlib 模块。

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      algorithm: "gzip",
    }),
  ],
};

function

允许你指定自定义压缩函数。

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      algorithm(input, compressionOptions, callback) {
        return compressionFunction(input, compressionOptions, callback);
      },
    }),
  ],
};

compressionOptions

类型

type compressionOptions = {
  flush?: number;
  finishFlush?: number;
  chunkSize?: number;
  windowBits?: number;
  level?: number;
  memLevel?: number;
  strategy?: number;
  dictionary?: Buffer | TypedArray | DataView | ArrayBuffer;
  info?: boolean;
  maxOutputLength?: number;
};

默认值:{ level: 9 }

algorithm 的压缩选项。

你可以在 zlib 文档中找到所有可用选项。

[!注意]

如果你为 algorithm 选项使用自定义函数,则 compressionOptions 的默认值将为空对象 {}

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      compressionOptions: { level: 1 },
    }),
  ],
};

threshold

类型

type threshold = number;

默认值:0

仅处理大于此大小(以字节为单位)的资产。

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      threshold: 8192,
    }),
  ],
};

minRatio

类型

type minRatio = number;

默认值:0.8

仅处理压缩率优于此比率的资产(minRatio = 压缩大小 / 原始大小)。例如,如果你有一个大小为 1024 字节的 image.png 文件,并且其压缩版本为 768 字节,则 minRatio0.75。换句话说,只有当 压缩大小 / 原始大小 的比率小于指定的 minRatio 时,才会处理资产。

你可以使用值 1 来处理小于或等于原始大小的资产。

使用值 Infinity 来处理所有资产,即使它们大于原始大小或其原始大小为 0 字节(当你为 AWS 预压缩所有资产时很有用)。

使用值 Number.MAX_SAFE_INTEGER 来处理所有资产,即使它们大于原始大小,但不包括原始大小为 0 字节的资产。

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      // Compress all assets, including files with `0` bytes size
      // minRatio: Infinity

      // Compress all assets, excluding files with `0` bytes size
      // minRatio: Number.MAX_SAFE_INTEGER

      minRatio: 0.8,
    }),
  ],
};

filename

类型

type filename = string | ((pathdata: PathData) => string);

默认值:"[path][base].gz"

目标资产文件名。

string

例如,给定资产路径:assets/images/image.png?foo=bar#hash

[path] 被原始资产的目录替换,包括尾随的 / (assets/images/)。

[file] 被原始资产的路径替换 (assets/images/image.png)。

[base] 被原始资产的基本名称 ([name] + [ext]) 替换 (image.png)。

[name] 被原始资产的名称替换 (image)。

[ext] 被原始资产的扩展名替换,包括 . (.png)。

[query] 被原始资产的查询部分替换,包括 ? (?foo=bar)。

[fragment] 被原始资产的片段(在 URL 概念中称为 hash)替换 (#hash)。

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      filename: "[path][base].gz",
    }),
  ],
};

function

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      filename(pathData) {
        // The `pathData` argument contains all placeholders - `path`/`name`/`ext`/etc
        // Available properties described above, for the `String` notation
        if (/\.svg$/.test(pathData.filename)) {
          return "assets/svg/[path][base].gz";
        }

        return "assets/js/[path][base].gz";
      },
    }),
  ],
};

deleteOriginalAssets

类型

type deleteOriginalAssets =
  | boolean
  | "keep-source-map"
  | ((name: string) => boolean);

默认值:false

确定原始(未压缩)资产是否应在压缩后删除。

  • 如果设置为 true,所有原始资产都将被删除。

  • 如果设置为 "keep-source-map",所有原始资产(除了源映射文件 .map)都将被删除。

  • 如果提供了函数,它将使用每个资产的名称进行调用,并且应返回 true 以删除资产,或返回 false 以保留资产。

示例

module.exports = {
  plugins: [
    new CompressionPlugin({
      deleteOriginalAssets: (assetName) => {
        // Delete all assets except images
        return !assetName.endsWith(".png") && !assetName.endsWith(".jpg");
      },
    }),
  ],
};

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      deleteOriginalAssets: true,
    }),
  ],
};

排除源映射文件不进行压缩

module.exports = {
  plugins: [
    new CompressionPlugin({
      exclude: /.map$/,
      deleteOriginalAssets: "keep-source-map",
    }),
  ],
};

使用自定义函数

module.exports = {
  plugins: [
    new CompressionPlugin({
      exclude: /.map$/,
      deleteOriginalAssets: (name) => {
        if (/\.js$/.test(name)) {
          return false;
        }

        return true;
      },
    }),
  ],
};

示例

使用 Zopfli

使用 zopfli 库准备资产的压缩版本。

[!注意]

@gfx/zopfli 需要至少 Node.js 版本 8

首先,你需要安装 @gfx/zopfli

$ npm install @gfx/zopfli --save-dev

webpack.config.js

const zopfli = require("@gfx/zopfli");

module.exports = {
  plugins: [
    new CompressionPlugin({
      compressionOptions: {
        numiterations: 15,
      },
      algorithm(input, compressionOptions, callback) {
        return zopfli.gzip(input, compressionOptions, callback);
      },
    }),
  ],
};

使用 Brotli

Brotli 是一种最初由 Google 开发的压缩算法,提供优于 gzip 的压缩效果。

Node.js v10.16.0 及更高版本在其 zlib 模块中包含了对 Brotli 压缩的原生支持

你只需将适当的 algorithm 传递给 CompressionPlugin,即可利用 Node 10.16.0 及更高版本中内置的 Brotli 支持。

webpack.config.js

const zlib = require("zlib");

module.exports = {
  plugins: [
    new CompressionPlugin({
      filename: "[path][base].br",
      algorithm: "brotliCompress",
      test: /\.(js|css|html|svg)$/,
      compressionOptions: {
        params: {
          [zlib.constants.BROTLI_PARAM_QUALITY]: 11,
        },
      },
      threshold: 10240,
      minRatio: 0.8,
      deleteOriginalAssets: false,
    }),
  ],
};

[!NOTE] Brotli 的 BROTLI_PARAM_QUALITY 选项在功能上等同于 zlib 的 level 选项。你可以在 zlib 模块文档的相关部分中找到所有 Brotli 选项。

使用 Zstandard

Zstandard (zstd) 是一种快速的无损压缩算法,旨在实现 zlib 级别及更高的压缩比,适用于实时压缩场景。

Node.js 22.15.0 及更高版本在其 zlib 模块中包含了对 Zstandard 压缩的原生支持

你只需将适当的 algorithm 传递给 CompressionPlugin,即可利用 Node 22.15.0 及更高版本中内置的 zstd 支持。

webpack.config.js

const zlib = require("zlib");

module.exports = {
  plugins: [
    new CompressionPlugin({
      filename: "[path][base].zst",
      algorithm: "zstdCompress",
      test: /\.(js|css|html|svg)$/,
      compressionOptions: {
        params: {
          [zlib.constants.ZSTD_c_compressionLevel]: 10,
        },
      },
      threshold: 10240,
      minRatio: 0.8,
      deleteOriginalAssets: false,
    }),
  ],
};

你可以在 zlib 模块文档的相关部分中找到所有 Zstandard 选项。

不同算法的多个压缩版本资产

webpack.config.js

const zlib = require("zlib");

module.exports = {
  plugins: [
    new CompressionPlugin({
      filename: "[path][base].gz",
      algorithm: "gzip",
      test: /\.js$|\.css$|\.html$/,
      threshold: 10240,
      minRatio: 0.8,
    }),
    new CompressionPlugin({
      filename: "[path][base].br",
      algorithm: "brotliCompress",
      test: /\.(js|css|html|svg)$/,
      compressionOptions: {
        params: {
          [zlib.constants.BROTLI_PARAM_QUALITY]: 11,
        },
      },
      threshold: 10240,
      minRatio: 0.8,
    }),
  ],
};

贡献

我们欢迎贡献!

如果你尚未阅读,请花一点时间阅读我们的贡献指南。

CONTRIBUTING

许可证

MIT

ContextExclusionPlugin

Context 指的是 带有表达式的 require,例如 require('./locale/' + name + '.json')

ContextExclusionPlugin 允许你排除 context。在初始化插件时提供 RegExp 作为参数,以排除所有匹配的 context。

webpack.config.js

module.exports = {
  plugins: [new webpack.ContextExclusionPlugin(/dont/)],
};

ContextReplacementPlugin

Context 指的是 带有表达式的 require,例如 require('./locale/' + name + '.json')。当遇到此类表达式时,webpack 会推断出目录('./locale/')和正则表达式(/^.*\.json$/)。由于 name 在编译时未知,webpack 会将每个文件作为模块包含在 bundle 中。

ContextReplacementPlugin 允许你覆盖推断出的信息。配置插件有多种方式:

用法

new webpack.ContextReplacementPlugin(
  resourceRegExp: RegExp,
  newContentResource?: string,
  newContentRecursive?: boolean,
  newContentRegExp?: RegExp
)

如果资源(目录)与 resourceRegExp 匹配,插件会将默认资源、递归标志或生成的正则表达式分别替换为 newContentResourcenewContentRecursivenewContextRegExp。如果 newContentResource 是相对路径,它将相对于前一个资源进行解析。

这是一个限制模块使用的小例子:

new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /de|fr|hu/);

moment/locale context 被限制为匹配 /de|fr|hu/ 的文件。因此,只包含这些 locales(有关详细信息,请参阅 此问题)。

内容回调

new webpack.ContextReplacementPlugin(
  resourceRegExp: RegExp,
  newContentCallback: (data) => void
);

newContentCallback 函数会获得一个 ContextModuleFactorydata 对象,并期望覆盖所提供对象的 request 属性。

使用此回调,我们可以动态地将请求重定向到新位置:

new webpack.ContextReplacementPlugin(/^\.\/locale$/, (context) => {
  if (!/\/moment\//.test(context.context)) return;

  Object.assign(context, {
    regExp: /^\.\/\w+/,
    request: '../../locale', // resolved relatively
  });
});

其他选项

newContentResourcenewContentCreateContextMap 参数也可用。

new webpack.ContextReplacementPlugin(
  resourceRegExp: RegExp,
  newContentResource: string,
  newContentCreateContextMap: object // mapping runtime-request (userRequest) to compile-time-request (request)
);

这两个参数可以一起使用,以更具针对性的方式重定向请求。newContentCreateContextMap 允许你以对象形式将运行时请求映射到编译请求:

new ContextReplacementPlugin(/selector/, './folder', {
  './request': './request',
  './other-request': './new-request',
});

CopyWebpackPlugin

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 stats API 中的 资产对象 获取原始源文件名。

选项

插件用法

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 path, can be files, directories or globs. See examples below.
      ],
      options: {
        concurrency: 100,
      },
    }),
  ],
};

Patterns

from

类型

type from = string;

默认值:undefined

用于复制文件的 glob 模式或路径。Globs 遵循 fast-glob 模式语法。注意:Globs 必须是 string 类型。

[!警告]

如果 from 选项是 glob(即 path\to\file.ext),请不要直接在其中使用 \\,因为在 UNIX 系统上反斜杠被视为普通字符(而不是路径分隔符)。在 Windows 上,正斜杠和反斜杠都用作分隔符。请改用 /,或使用 Node 的 path 工具来规范化路径。

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 值是 globfile 还是 dir。请参阅更多 示例

to

类型

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

默认值:compiler.options.output

string

指定输出路径。

[!警告]

不要直接在 to 路径(例如 path\to\dest)选项中使用 \\,因为在 UNIX 系统上反斜杠被视为普通字符(而不是路径分隔符)。在 Windows 上,正斜杠和反斜杠都用作分隔符。请改用 /,或使用 Node 的 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 上,正斜杠和反斜杠都用作分隔符。请改用 /,或使用 Node 的 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. 它会从结果路径的开头移除。

[!警告]

不要直接在 to(即 path\to\newFile)选项中使用 \\,因为在 UNIX 系统上反斜杠被视为普通字符(而不是路径分隔符)。在 Windows 上,正斜杠和反斜杠都用作分隔符。请改用 /,或使用 Node 的 path 工具来规范化路径。

webpack.config.js

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

context 可以是绝对路径或相对路径。如果是相对路径,则会根据 compiler.options.context 转换为绝对路径。

from 使用 glob 模式时,你应该显式定义 context。否则,插件会根据 from 的性质自动设置它:

  • 如果 from 是文件,则 context 默认为文件所在的目录。结果路径将仅是文件名本身。

  • 如果 from 是目录,则 context 设置为同一目录。结果路径将包含目录的内容(包括子目录),相对于它。

context 的使用在这些示例中进行了说明。

globOptions

[!警告]

onlyDirectories 不起作用,因为插件旨在复制文件,而不是单独复制目录。

类型

type globOptions = import("tinyglobby").GlobOptions;

默认值:undefined

允许你配置插件使用的 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;

默认值:undefined

[!注意]

要按路径(例如,按扩展名或名称)忽略文件,请优先使用 [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";

默认值:undefined

确定 to 选项的类型——它是目录、文件还是模板。有时很难判断 to 是什么,例如 path/to/dir-with.ext。如果你想将文件复制到目录中,你应该明确将类型设置为 dir。在大多数情况下,插件会自动确定正确的 type,因此你通常无需手动设置此选项。

名称类型默认值描述
'dir'stringundefined使用的 to 没有扩展名或以 '/' 结尾。
'file'stringundefinedto 是文件路径而不是目录或模板时使用。
'template'stringundefinedto 包含模板模式时使用。
'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 选项设置为 truewebpack.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);

默认值:undefined

允许你在文件写入输出目录之前修改其内容。

function

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to: "dest/",
          // The `content` argument is a [`Buffer`](https://node.org.cn/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
名称默认值描述
transformerundefined允许你修改文件内容。
cachefalse启用 transform 的缓存。你可以使用 transform: { cache: { key: 'my-cache-key' } } 在需要时手动使缓存失效。
transformer

类型

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

默认值:undefined

webpack.config.js

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

默认值:undefined

允许你修改多个文件的内容并将合并结果保存到单个文件中。

[!注意]

必须指定 to 选项并指向文件。文件名中只允许使用 [contenthash][fullhash] 模板字符串。

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/**/*.txt",
          to: "dest/file.txt",
          // The `assets` argument is an array of assets matched by 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.org.cn/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>);

默认值:undefined

允许添加资产信息。

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        "relative/path/to/file.ext",
        {
          from: "**/*",
          // Terser skip this file for minification
          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

type concurrency = number;

默认值:100

限制对文件系统的同时请求数量。

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

从技术上讲,这等同于使用 **/* 并将预定义上下文设置为指定目录。

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

从技术上讲,这是一个文件名,其预定义上下文等于文件所在的目录 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",
        },
      ],
    }),
  ],
};

贡献

我们欢迎所有贡献!

如果你是新用户,请在提交问题或拉取请求之前花一些时间阅读我们的贡献指南。

CONTRIBUTING

许可证

MIT

CssMinimizerWebpackPlugin

npm node tests cover discussion size

此插件使用 cssnano 来优化和压缩你的 CSS。

它作为 optimize-css-assets-webpack-plugin 的更精确替代方案,对源映射、带查询字符串的资产、缓存和并行处理有更好的支持。

入门

首先,你需要安装 css-minimizer-webpack-plugin

npm install css-minimizer-webpack-plugin --save-dev

yarn add -D css-minimizer-webpack-plugin

pnpm add -D css-minimizer-webpack-plugin

然后将插件添加到你的 webpack 配置中。例如:

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.s?css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
      },
    ],
  },
  optimization: {
    minimizer: [
      // For webpack v5, you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line // `...`,
      new CssMinimizerPlugin(),
    ],
  },
  plugins: [new MiniCssExtractPlugin()],
};

[!注意]

默认情况下,这只在生产模式下启用 CSS 优化。

要在开发模式下也启用它,请将 optimization.minimize 选项设置为 true

webpack.config.js

// [...]
module.exports = {
  optimization: {
    // [...]
    minimize: true,
  },
};

最后,使用你偏好的方法运行 Webpack。

关于源映射的注意事项

此插件仅适用于 devtool 选项的 source-mapinline-source-maphidden-source-mapnosources-source-map 值。

为什么?因为 CSS 仅支持这些源映射类型。

该插件尊重 devtool 设置并内部使用 SourceMapDevToolPlugin

使用受支持的 devtool 值可启用源映射生成。

SourceMapDevToolPlugin 中启用 columns 选项也允许生成源映射。

使用源映射将错误消息位置映射到其原始模块(请注意,这可能会减慢编译速度)。

如果你使用自己的 minify 函数,请参阅 minify 部分以正确处理源映射。

选项

名称类型默认值描述
testString|RegExp|Array<String|RegExp>/\.css(\?.*)?$/i用于匹配文件的测试。
includeString|RegExp|Array<String|RegExp>undefined要包含的文件。
excludeString|RegExp|Array<String|RegExp>undefined要排除的文件。
parallelBoolean|Numbertrue启用或禁用多进程并行运行。
minifyFunction|Array<Function>CssMinimizerPlugin.cssnanoMinify允许覆盖默认的压缩函数。
minimizerOptionsObject|Array<Object>{ preset: 'default' }Cssnano 优化选项
warningsFilterFunction<(warning, file, source) -> Boolean>() => true允许过滤 css-minimizer 警告。

test

  • 类型:String|RegExp|Array<String|RegExp>
  • 默认值:/\.css(\?.*)?$/i

用于匹配文件的测试。

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        test: /\.foo\.css$/i,
      }),
    ],
  },
};

include

  • 类型:String|RegExp|Array<String|RegExp>
  • 默认值:undefined

要包含的文件。

webpack.config.js

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

exclude

  • 类型:String|RegExp|Array<String|RegExp>
  • 默认值:undefined

要排除的文件。

webpack.config.js

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

parallel

  • 类型:Boolean|Number
  • 默认值:true

使用多进程并行运行以提高构建速度。

默认并发运行数量:os.cpus().length - 1os.availableParallelism() - 1(如果此函数受支持)。

ℹ️ 并行化可以显著加快你的构建速度,因此强烈推荐。如果启用了并行化,minimizerOptions 中的包必须通过字符串(packageNamerequire.resolve(packageName))引入。在minimizerOptions中阅读更多内容。

Boolean

启用或禁用多进程并行运行。

webpack.config.js

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

Number

启用多进程并行运行并指定并发运行的数量。

webpack.config.js

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

minify

  • 类型:Function|Array<Function>
  • 默认值:CssMinimizerPlugin.cssnanoMinify

覆盖默认的压缩函数。

默认情况下,插件使用 cssnano 包。

这在测试或使用未发布版本或分支时很有用。

可选选项:

  • CssMinimizerPlugin.cssnanoMinify
  • CssMinimizerPlugin.cssoMinify
  • CssMinimizerPlugin.cleanCssMinify
  • CssMinimizerPlugin.esbuildMinify
  • CssMinimizerPlugin.lightningCssMinify(以前是CssMinimizerPlugin.parcelCssMinify,包已重命名,但我们为了向后兼容保留它)
  • async (data, inputMap, minimizerOptions) => {return {code: "a{color: red}", map: "...", warnings: [], errors: []}}

[!警告]

当启用了 parallel 选项时,总是在 minify 函数内部使用 require.

Function

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minimizerOptions: {
          level: {
            1: {
              roundingPrecision: "all=3,px=5",
            },
          },
        },
        minify: CssMinimizerPlugin.cleanCssMinify,
      }),
    ],
  },
};

Array

如果一个函数数组传递给 minify 选项,则 minimizerOptions 也必须是一个数组。

minify 数组中的函数索引对应于 minimizerOptions 数组中具有相同索引的选项对象。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minimizerOptions: [
          {}, // Options for the first function (CssMinimizerPlugin.cssnanoMinify)
          {}, // Options for the second function (CssMinimizerPlugin.cleanCssMinify)
          {}, // Options for the third function
        ],
        minify: [
          CssMinimizerPlugin.cssnanoMinify,
          CssMinimizerPlugin.cleanCssMinify,
          async (data, inputMap, minimizerOptions) => {
            //  Custom minifier function
            return {
              code: `a{color: red}`,
              map: `{"version": "3", ...}`,
              warnings: [],
              errors: [],
            };
          },
        ],
      }),
    ],
  },
};

minimizerOptions

  • 类型:Object|Array<Object>
  • 默认值:{ preset: 'default' }

Cssnano 优化选项

Object

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minimizerOptions: {
          preset: [
            "default",
            {
              discardComments: { removeAll: true },
            },
          ],
        },
      }),
    ],
  },
};

Array

minify 数组中的函数索引对应于 minimizerOptions 数组中具有相同索引的选项对象。

如果你将 minimizerOptions 作为对象使用,所有 minify 函数都将接受它。

如果启用了并行化,minimizerOptions 中的包必须通过字符串(packageNamerequire.resolve(packageName))引用。在这种情况下,我们不应该使用 require/import

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minimizerOptions: {
          preset: require.resolve("cssnano-preset-simple"),
        },
      }),
    ],
  },
};
processorOptions (⚠ 仅限 cssnano)
  • 类型:Object
  • 默认值:{ from: assetName }

允许过滤 cssnano 的 processoptions 选项。

parserstringifiersyntax 可以是函数或指示将被导入的模块的字符串。

[!警告]

如果这些选项中的任何一个作为函数传递,则必须禁用 parallel 选项。.

import sugarss from "sugarss";

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        parallel: false,
        minimizerOptions: {
          processorOptions: {
            parser: sugarss,
          },
        },
      }),
    ],
  },
};
module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minimizerOptions: {
          processorOptions: {
            parser: "sugarss",
          },
        },
      }),
    ],
  },
};

warningsFilter

  • 类型:Function<(warning, file, source) -> Boolean>
  • 默认值:() => true

过滤 css-minimizer 警告(默认情况下为 cssnano)。

返回 true 以保留警告,或返回一个 falsy 值(false/null/undefined)以抑制它。

[!警告]

除非启用了源映射,否则 source 参数将为 undefined

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        warningsFilter: (warning, file, source) => {
          if (/Dropping unreachable code/i.test(warning)) {
            return true;
          }

          if (/file\.css/i.test(file)) {
            return true;
          }

          if (/source\.css/i.test(source)) {
            return true;
          }

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

示例

使用源映射

不要忘记为所有加载器启用 sourceMap 选项。

const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
  devtool: "source-map",
  module: {
    rules: [
      {
        test: /\.s?css$/,
        use: [
          MiniCssExtractPlugin.loader,
          { loader: "css-loader", options: { sourceMap: true } },
          { loader: "sass-loader", options: { sourceMap: true } },
        ],
      },
    ],
  },
  optimization: {
    minimizer: [new CssMinimizerPlugin()],
  },
  plugins: [new MiniCssExtractPlugin()],
};

删除所有注释

删除所有注释,包括以 /*! 开头的注释。

module.exports = {
  optimization: {
    minimizer: [
      new CssMinimizerPlugin({
        minimizerOptions: {
          preset: [
            "default",
            {
              discardComments: { removeAll: true },
            },
          ],
        },
      }),
    ],
  },
};

使用自定义压缩器 csso

webpack.config.js

module.exports = {
  // Uncomment if you need source maps
  // devtool: "source-map",
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minify: CssMinimizerPlugin.cssoMinify,
        // Uncomment this line for options
        // minimizerOptions: { restructure: false },
      }),
    ],
  },
};

使用自定义压缩器 clean-css

webpack.config.js

module.exports = {
  // Uncomment if you need source maps
  // devtool: "source-map",
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minify: CssMinimizerPlugin.cleanCssMinify,
        // Uncomment this line for options
        // minimizerOptions: { compatibility: 'ie11,-properties.merging' },
      }),
    ],
  },
};

使用自定义压缩器 esbuild

webpack.config.js

module.exports = {
  // Uncomment if you need source maps
  // devtool: "source-map",
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minify: CssMinimizerPlugin.esbuildMinify,
      }),
    ],
  },
};

使用自定义压缩器 lightningcss,以前是 @parcel/css

webpack.config.js

module.exports = {
  // devtool: "source-map", // Uncomment for source maps
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minify: CssMinimizerPlugin.lightningCssMinify,
        // Uncomment this line for options
        // minimizerOptions: { targets: { ie: 11 }, drafts: { nesting: true } },
      }),
    ],
  },
};

使用自定义压缩器 swc

webpack.config.js

module.exports = {
  // devtool: "source-map", // Uncomment for source maps
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minify: CssMinimizerPlugin.swcMinify,
        // Uncomment this line for options
        // minimizerOptions: {},
      }),
    ],
  },
};

贡献

我们欢迎所有贡献!

如果你是新用户,请花一些时间阅读我们的贡献指南。

CONTRIBUTING

许可证

MIT

DefinePlugin

DefinePlugin 在**编译**时将代码中的变量替换为其他值或表达式。这对于在开发构建和生产构建之间实现不同行为非常有用。如果你在开发构建中进行日志记录,但在生产构建中不进行,则可以使用全局常量来确定是否进行日志记录。这正是 DefinePlugin 的用武之地,它为开发和生产构建设置了“一劳永逸”的规则。

new webpack.DefinePlugin({
  // Definitions...
});

用法

传递给 DefinePlugin 的每个键都是一个标识符或多个用 . 连接的标识符。

  • 如果值是字符串,它将用作代码片段。
  • 如果值不是字符串,它将被字符串化(包括函数)。
  • 如果值是对象,所有键的定义方式都相同。
  • 如果你在键前加上 typeof,则它仅在 typeof 调用中定义。

这些值将内联到代码中,从而允许通过压缩来移除冗余的条件判断。

new webpack.DefinePlugin({
  PRODUCTION: JSON.stringify(true),
  VERSION: JSON.stringify('5fa3b9'),
  BROWSER_SUPPORTS_HTML5: true,
  TWO: '1+1',
  'typeof window': JSON.stringify('object'),
  'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
});
console.log('Running App version ' + VERSION);
if (!BROWSER_SUPPORTS_HTML5) require('html5shiv');
if (!PRODUCTION) {
  console.log('Debug info');
}

if (PRODUCTION) {
  console.log('Production log');
}

未经压缩的 webpack 处理后结果为:

if (!true) {
  console.log('Debug info');
}
if (true) {
  console.log('Production log');
}

然后在压缩后结果为:

console.log('Production log');

功能标志

使用功能标志在生产/开发构建中启用/禁用功能。

new webpack.DefinePlugin({
  NICE_FEATURE: JSON.stringify(true),
  EXPERIMENTAL_FEATURE: JSON.stringify(false),
});

服务 URL

在生产/开发构建中使用不同的服务 URL

new webpack.DefinePlugin({
  SERVICE_URL: JSON.stringify('https://dev.example.com'),
});

通过 runtimeValue 获取运行时值

function (getterFunction, [string] | true | object) => getterFunction()

可以定义变量,其值依赖于文件,并且当这些文件在文件系统中更改时会重新评估。这意味着当这些被监视的文件更改时,webpack 将重新构建。

webpack.DefinePlugin.runtimeValue 函数有两个参数:

  • 第一个参数是一个 function(module, key, version),它应该返回要分配给定义的值。

  • 第二个参数可以是要监视的文件路径数组,也可以是 true 来标记模块不可缓存。从 5.26.0 开始,它还可以接受一个带有以下属性的对象参数:

    • fileDependencies?: string[] 函数所依赖的文件列表。
    • contextDependencies?: string[] 函数所依赖的目录列表。
    • missingDependencies?: string[] 函数所依赖的不存在的文件列表。
    • buildDependencies?: string[] 函数所依赖的构建依赖项列表。
    • version?: string | () => string 函数的版本。
const fileDep = path.resolve(__dirname, 'sample.txt');

new webpack.DefinePlugin({
  BUILT_AT: webpack.DefinePlugin.runtimeValue(Date.now, {
    fileDependencies: [fileDep],
  }),
});

BUILT_AT 的值将是 'sample.txt' 在文件系统中最后更新的时间,例如 1597953013291

DllPlugin

DllPluginDllReferencePlugin 提供了拆分 bundles 的方法,可以显著提高构建时间性能。“DLL”一词代表动态链接库,最初由微软引入。

DllPlugin

此插件在单独的 webpack 配置中专门用于创建 dll-only-bundle。它创建一个 manifest.json 文件,该文件由 DllReferencePlugin 用于映射依赖项。

  • context (可选):manifest 文件中请求的 context(默认为 webpack context)。
  • format (boolean = false):如果为 true,则 manifest json 文件(输出)将被格式化。
  • name:公开的 dll 函数的名称(模板路径[fullhash], [chunkhash], [contenthash], & [name]
  • path:manifest json 文件(输出)的绝对路径
  • entryOnly (boolean = true):如果为 true,则只公开入口点。
  • type:dll bundle 的类型。
new webpack.DllPlugin(options);

创建一个 manifest.json 文件,并写入给定 path。它包含从 require 和 import 请求到模块 ID 的映射。它由 DllReferencePlugin 使用。

将此插件与 output.library 选项结合使用,以公开(即,放入全局作用域)dll 函数。

DllReferencePlugin

此插件用于主要的 webpack 配置中,它引用 dll-only-bundle(s) 以按需引入预构建的依赖项。

  • context:(绝对路径)manifest(或 content 属性)中请求的 context。
  • extensions:用于解析 dll bundle 中模块的扩展名(仅在使用 'scope' 时使用)。
  • manifest:一个包含 contentname 的对象,或者一个指向编译时加载的 JSON manifest 绝对路径的字符串。
  • content (可选):从请求到模块 ID 的映射(默认为 manifest.content)。
  • name (可选):dll 公开的标识符(默认为 manifest.name)(另请参阅 externals)。
  • scope (可选):用于访问 dll 内容的前缀。
  • sourceType (可选):dll 的公开方式(libraryTarget)。
new webpack.DllReferencePlugin(options);

引用 dll manifest 文件,将依赖名称映射到模块 ID,然后根据需要使用内部 __webpack_require__ 函数引入它们。

模式

此插件可用于两种不同的模式:作用域模式映射模式

作用域模式

dll 的内容可在模块前缀下访问。即,当 scope = 'xyz' 时,dll 中的文件 abc 可通过 require('xyz/abc') 访问。

映射模式

dll 的内容被映射到当前目录。如果所需的 file 与 dll 中的文件匹配(解析后),则使用 dll 中的文件代替。

由于这发生在解析 dll bundle 中的每个文件之后,因此 dll bundle 的消费者必须可以使用相同的路径。即,如果 dll 包含 lodash 和文件 abc,则 require('lodash')require('./abc') 将从 dll 中使用,而不是将它们构建到主 bundle 中。

用法

webpack.vendor.config.js

const path = require('path');

new webpack.DllPlugin({
  context: __dirname,
  name: '[name]_[fullhash]',
  path: path.join(__dirname, 'manifest.json'),
});

webpack.app.config.js

new webpack.DllReferencePlugin({
  context: __dirname,
  manifest: require('./manifest.json'),
  scope: 'xyz',
  sourceType: 'commonjs2',
});

示例

供应商用户

两个独立的示例文件夹。演示了作用域和上下文。

参考

来源

测试

EnvironmentPlugin

EnvironmentPlugin 是在 process.env 键上使用 DefinePlugin 的简写形式。

用法

EnvironmentPlugin 接受键数组或将其键映射到其默认值的对象。

new webpack.EnvironmentPlugin(['NODE_ENV', 'DEBUG']);

这等同于以下 DefinePlugin 应用:

new webpack.DefinePlugin({
  'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
  'process.env.DEBUG': JSON.stringify(process.env.DEBUG),
});

使用默认值

或者,EnvironmentPlugin 支持一个对象,该对象将键映射到其默认值。如果 process.env 中未定义键,则取键的默认值。

new webpack.EnvironmentPlugin({
  NODE_ENV: 'development', // use 'development' unless process.env.NODE_ENV is defined
  DEBUG: false,
});

示例

让我们研究在测试文件 entry.js 上运行先前的 EnvironmentPlugin 配置时的结果:

if (process.env.NODE_ENV === 'production') {
  console.log('Welcome to production');
}
if (process.env.DEBUG) {
  console.log('Debugging output');
}

当在终端中执行 NODE_ENV=production webpack 进行构建时,entry.js 变为:

if ('production' === 'production') {
  // <-- 'production' from NODE_ENV is taken
  console.log('Welcome to production');
}
if (false) {
  // <-- default value is taken
  console.log('Debugging output');
}

运行 DEBUG=false webpack 得到:

if ('development' === 'production') {
  // <-- default value is taken
  console.log('Welcome to production');
}
if ('false') {
  // <-- 'false' from DEBUG is taken
  console.log('Debugging output');
}

用例:Git 版本

以下 EnvironmentPlugin 配置提供了 process.env.GIT_VERSION(例如“v5.4.0-2-g25139f57f”)和 process.env.GIT_AUTHOR_DATE(例如“2020-11-04T12:25:16+01:00”),对应于仓库的最后一次 Git 提交:

const child_process = require('child_process');
function git(command) {
  return child_process.execSync(`git ${command}`, { encoding: 'utf8' }).trim();
}

new webpack.EnvironmentPlugin({
  GIT_VERSION: git('describe --always'),
  GIT_AUTHOR_DATE: git('log -1 --format=%aI'),
});

DotenvPlugin

第三方 DotenvPlugin (dotenv-webpack) 允许你公开(一部分)dotenv 变量

// .env
DB_HOST=127.0.0.1
DB_PASS=foobar
S3_API=mysecretkey
new Dotenv({
  path: './.env', // Path to .env file (this is the default)
  safe: true, // load .env.example (defaults to "false" which does not use dotenv-safe)
});

EslintWebpackPlugin

npm node tests coverage discussion size

此版本的 eslint-webpack-plugin 仅支持 webpack 5。对于 webpack 4,请参阅 2.x 分支

此插件使用 ESLint 在 Webpack 构建过程中查找并修复你的 JavaScript 代码问题。

入门

首先,你需要安装 eslint-webpack-plugin

npm install eslint-webpack-plugin --save-dev

yarn add -D eslint-webpack-plugin

pnpm add -D eslint-webpack-plugin

[!注意]

如果你还没有安装,还需要从 npm 安装 eslint >= 8

npm install eslint --save-dev

yarn add -D eslint

pnpm add -D eslint

然后将插件添加到您的 webpack 配置中。例如

const ESLintPlugin = require('eslint-webpack-plugin');

module.exports = {
  // ...
  plugins: [new ESLintPlugin(options)],
  // ...
};

选项

你可以传递 ESLint Node.js API 选项

[!注意]

你提供的配置选项将传递给 ESLint 类。这与你在 package.jsoneslint.config.js(从 ESLint v9.0.0 开始,以前是 .eslintrc)中指定的选项集不同。有关详细信息,请参阅 ESLint 文档

[!警告]

在 eslint-webpack-plugin 版本 1 中,选项被传递给了现在已废弃的 CLIEngine

cache

  • 类型
type cache = boolean;
  • 默认值:true

缓存默认启用以减少执行时间。

cacheLocation

  • 类型
type cacheLocation = string;
  • 默认值:node_modules/.cache/eslint-webpack-plugin/.eslintcache

指定缓存位置的路径。可以是文件或目录。

configType

  • 类型
type configType = 'flat' | 'eslintrc';
  • 默认值:flat

指定 ESLint 使用的配置类型。

  • eslintrc 是大多数 ESLint 版本中可用的经典配置格式。
  • flat 是 ESLint 8.21.0 中引入的新格式。

新的配置格式在其自己的文档中进行了解释。

context

  • 类型
type context = string;
  • 默认值:compiler.context

linting 的基本目录。

eslintPath

  • 类型
type eslintPath = string;
  • 默认值:eslint

用于 linting 的 eslint 实例路径。

如果 eslintPath 是像官方 ESLint 一样的文件夹,或者指定了 formatter 选项,那么现在您无需安装 eslint

extensions

  • 类型
type extensions = string | Array<string>;
  • 默认值:'js'

指定应检查的文件扩展名。

exclude

  • 类型
type exclude = string | Array<string>;
  • 默认值:'node_modules'

指定要排除的文件/目录。必须是相对于 options.context 的路径。

resourceQueryExclude

  • 类型
type resourceQueryExclude = RegExp | Array<RegExp>;
  • 默认值:[]

指定要排除的资源查询。

files

  • 类型
type files = string | Array<string>;
  • 默认值:null

指定目录、文件或 glob 模式。必须是相对于 options.context 的路径。目录会递归遍历以查找匹配 options.extensions 的文件。文件和 glob 模式会忽略 options.extensions

fix

  • 类型
type fix = boolean;
  • 默认值:false

将启用 ESLint 自动修复功能

请注意:此选项将修改源文件。

formatter

  • 类型
type formatter = string| (
  results:  Array<import('eslint').ESLint.LintResult>,
  data?: import('eslint').ESLint.LintResultData | undefined
) => string
  • 默认值:'stylish'

接受一个函数,该函数将 ESLint 消息数组(对象)作为其参数,并且必须返回一个字符串作为输出。

您可以使用官方的 ESLint 格式化程序

lintDirtyModulesOnly

  • 类型
type lintDirtyModulesOnly = boolean;
  • 默认值:false

仅对更改的文件进行 lint,跳过构建开始时的初始 lint。

threads

  • 类型
type threads = boolean | number;
  • 默认值:false

将在线程池中运行 lint 任务。除非您指定一个数字,否则线程池大小是自动的。

错误和警告

默认情况下,插件将根据 ESLint 错误/警告的数量自动调整错误报告。

您仍然可以通过使用 emitError emitWarning 选项来强制此行为

emitError

  • 类型
type emitError = boolean;
  • 默认值:true

发现的错误将始终发出,要禁用请设置为 false

emitWarning

  • 类型
type emitWarning = boolean;
  • 默认值:true

发现的警告将始终发出,要禁用请设置为 false

failOnError

  • 类型
type failOnError = boolean;
  • 默认值:true

如果发现任何错误,将导致模块构建失败;要禁用请设置为 false

failOnWarning

  • 类型
type failOnWarning = boolean;
  • 默认值:false

如果设置为 true,则在发现任何警告时将导致模块构建失败。

quiet

  • 类型
type quiet = boolean;
  • 默认值:false

如果设置为 true,将只处理和报告错误并忽略警告。

outputReport

  • 类型
type outputReport =
  | boolean
  | {
      filePath?: string | undefined;
      formatter?:
        | (
            | string
            | ((
                results: Array<import('eslint').ESLint.LintResult>,
                data?: import('eslint').ESLint.LintResultData | undefined,
              ) => string)
          )
        | undefined;
    };
  • 默认值:false

将 ESLint 结果写入文件,例如用于 Jenkins CI 报告的 checkstyle xml 文件。

  • filePath:输出报告文件的路径(相对于 output.path 或绝对路径)。
  • formatter:您可以为输出文件传入不同的 formatter。如果未传入,则将使用默认/已配置的格式化程序。

更新日志

更新日志

贡献

我们欢迎所有贡献!

如果你是新用户,请花一些时间阅读我们的贡献指南。

CONTRIBUTING

许可证

MIT

EvalSourceMapDevToolPlugin

此插件可以更精细地控制源映射生成。它也会在 devtool 配置选项的某些设置下自动启用。

new webpack.EvalSourceMapDevToolPlugin(options);

选项

支持以下选项

  • test (string|RegExp|array):根据模块扩展名包含源映射(默认为 .js.css)。

  • include (string|RegExp|array):为匹配给定值的模块路径包含源映射。

  • exclude (string|RegExp|array):从源映射生成中排除匹配给定值的模块。

  • append (string|function):将给定值附加到原始资产。通常是 #sourceMappingURL 注释。[url] 会被替换为源映射文件的 URL。

    从版本 5.84.0 开始,webpack 允许 append 选项是一个函数,该函数接受路径数据和资产信息对象作为参数,并返回一个字符串。

    (pathData: PathData, assetInfo?: AssetInfo) => string;
  • moduleFilenameTemplate (string):请参阅 output.devtoolModuleFilenameTemplate

  • module (boolean):指示加载器是否应生成源映射(默认为 true)。

  • columns (boolean):指示是否应使用列映射(默认为 true)。

  • protocol (string):允许用户覆盖默认协议(webpack-internal://

示例

以下示例展示了此插件的一些常见用例。

基本用例

您可以使用以下代码替换配置选项 devtool: eval-source-map 为等效的自定义插件配置

module.exports = {
  // ...
  devtool: false,
  plugins: [new webpack.EvalSourceMapDevToolPlugin({})],
};

排除供应商映射

以下代码将排除 vendor.js 包中任何模块的源映射

new webpack.EvalSourceMapDevToolPlugin({
  exclude: ['vendor.js'],
});

HashedModuleIdsPlugin

此插件将使哈希基于模块的相对路径,生成一个四字符字符串作为模块 ID。建议在生产环境中使用。

new webpack.ids.HashedModuleIdsPlugin({
  // Options...
});

选项

此插件支持以下选项

  • context:用于创建名称的上下文目录(绝对路径)。
  • hashFunction:要使用的哈希算法,默认为 'md4'。支持 Node.JS 的 crypto.createHash 中的所有函数。
  • hashDigest:生成哈希时使用的编码,默认为 'base64'。支持 Node.JS 的 hash.digest 中的所有编码。
  • hashDigestLength:要使用的哈希摘要的前缀长度,默认为 4。请注意,为了避免模块 ID 冲突,某些生成的 ID 可能比此处指定的更长。

用法

以下是此插件可能如何使用的示例

new webpack.ids.HashedModuleIdsPlugin({
  context: __dirname,
  hashFunction: 'sha256',
  hashDigest: 'hex',
  hashDigestLength: 20,
});

HotModuleReplacementPlugin

启用 模块热替换,也称为 HMR。

基本用法

启用 HMR 很简单,在大多数情况下无需任何选项。

new webpack.HotModuleReplacementPlugin({
  // Options...
});

HtmlMinimizerWebpackPlugin

npm node tests cover discussion size

此插件可以使用 3 种工具来优化和缩小您的 HTML

  • swc - 一个非常快速的基于 Rust 的 Web 平台。
  • html-minifier-terser(默认) - 基于 JavaScript 的 HTML 缩小器。
  • @minify-html/node - 一个精心优化以提高速度和效率的 Rust HTML 缩小器,具有其他语言的绑定。

此插件无缝集成到您的 Webpack 构建管道中,以减小 HTML 大小并提高加载性能。

入门

首先,您需要安装 html-minimizer-webpack-plugin

npm install html-minimizer-webpack-plugin --save-dev

yarn add -D html-minimizer-webpack-plugin

pnpm add -D html-minimizer-webpack-plugin

附加步骤:如果您想使用 @swc/html,则需要安装它

npm install @swc/html --save-dev

yarn add -D @swc/html

pnpm add -D @swc/html

附加步骤:如果您想使用 @minify-html/node,则需要安装它

npm install @minify-html/node --save-dev

yarn add -D @minify-html/node

pnpm add -D @minify-html/node

然后将插件添加到你的 webpack 配置中。例如:

webpack.config.js

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

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        type: "asset/resource",
      },
    ],
  },
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          context: path.resolve(__dirname, "dist"),
          from: "./src/*.html",
        },
      ],
    }),
  ],
  optimization: {
    minimize: true,
    minimizer: [
      // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
      // `...`

      // For `html-minifier-terser`:
      //
      new HtmlMinimizerPlugin(),

      // For `@swc/html`:
      //
      // HTML documents - HTML documents with `Doctype` and `<html>/`<head>`/`<body>` tags
      //
      // Options - https://github.com/swc-project/bindings/blob/main/packages/html/index.ts#L5
      //
      // new HtmlMinimizerPlugin({
      //   minify: HtmlMinimizerPlugin.swcMinify,
      //   minimizerOptions: {}
      // })
      //
      //
      // HTML fragments - HTML fragments, i.e. HTML files without doctype or used in `<template></template>` tags or HTML parts which injects into another HTML parts
      //
      // Options - https://github.com/swc-project/bindings/blob/main/packages/html/index.ts#L38
      //
      // new HtmlMinimizerPlugin({
      //   minify: HtmlMinimizerPlugin.swcMinifyFragment,
      //   minimizerOptions: {}
      // })
    ],
  },
};

[!注意]

默认情况下,HTML 只会在生产模式下被缩小。要在开发环境中启用缩小,请显式设置 optimization.minimize: true

最后,使用你通常使用的方法运行 webpack(例如,通过 CLI 或 npm 脚本)。

[!注意]

工具中删除和折叠空格的方式有所不同(默认情况下)。

  • @swc/html - 仅在安全位置(例如 - htmlbody 元素周围,head 元素内部以及元数据元素之间 - <meta>/script/link/等)删除和折叠空白。
  • html-minifier-terser - 始终将多个空白折叠为 1 个空格(从不完全删除),但您可以使用 options 更改它
  • @minify-html/node - 请阅读文档 https://github.com/wilsonzlin/minify-html#whitespace 以获取详细的空白处理行为。

选项

test

类型

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

默认值:/\.html(\?.*)?$/i

用于匹配文件的测试。

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new HtmlMinimizerPlugin({
        test: /\.foo\.html/i,
      }),
    ],
  },
};

include

类型

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

默认值:undefined

要包含以进行缩小的文件。

webpack.config.js

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

exclude

类型

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

默认值:undefined

要从缩小中排除的文件。

webpack.config.js

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

parallel

类型

type parallel = undefined | boolean | number;

默认值:true

启用多进程并行化以提高构建性能。

  • 如果为 true,则使用 os.cpus().length - 1os.availableParallelism() - 1(如果可用)。

  • 如果是 number,则设置并发工作进程的数量。

[!注意]

并行化可以显著加快您的构建速度,因此强烈推荐

boolean

启用或禁用多进程并行运行。

webpack.config.js

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

number

启用多进程并行运行并设置并发运行的数量。

webpack.config.js

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

minify

类型

type minify =
  | ((
      data: { [file: string]: string },
      minimizerOptions: {
        [key: string]: any;
      },
    ) => {
      code: string;
      errors?: unknown[] | undefined;
      warnings?: unknown[] | undefined;
    })
  | ((
      data: { [file: string]: string },
      minimizerOptions: {
        [key: string]: any;
      },
    ) => {
      code: string;
      errors?: unknown[] | undefined;
      warnings?: unknown[] | undefined;
    })[];

默认值:HtmlMinimizerPlugin.htmlMinifierTerser

允许您覆盖默认的缩小函数。默认情况下,插件使用 html-minifier-terser 包。

我们目前支持

  • HtmlMinimizerPlugin.swcMinify(用于压缩 HTML 文档,即包含 HTML 文档类型和 <html>/<body>/<head> 标签的文档)
  • HtmlMinimizerPlugin.swcMinifyFragment(用于压缩 HTML 片段,即当您有部分 HTML 将被插入到其他 HTML 部分时)
  • HtmlMinimizerPlugin.htmlMinifierTerser
  • HtmlMinimizerPlugin.minifyHtmlNode

[!注意]

swcMinifyswcMinifyFragment 之间的区别在于错误报告。如果您的 HTML 文档或片段中存在错误(无效或损坏的语法),您将收到错误。这使您可以在构建阶段查看所有错误和问题。

有助于使用和测试未发布的版本或分支。

[!警告]

parallel 选项启用时,始终在 minify 函数内部使用 require.

function

您可以定义一个自定义缩小函数,完全控制 HTML 的处理方式。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new HtmlMinimizerPlugin({
        minimizerOptions: {
          collapseWhitespace: true,
        },
        minify: (data, minimizerOptions) => {
          const htmlMinifier = require("html-minifier-terser");
          const [[filename, input]] = Object.entries(data);

          return {
            code: htmlMinifier.minify(input, minimizerOptions),
            warnings: [],
            errors: [],
          };
        },
      }),
    ],
  },
};

array

如果将函数数组传递给 minify 选项,则 minimizerOptions 可以是以下两种方式之一:

  • 数组;如果 minimizerOptions 是数组,则 minify 数组中的函数索引对应于 minimizerOptions 数组中具有相同索引的选项对象。

  • 单个对象;如果您将 minimizerOptions 用作对象,则所有 minify 函数都将接受它。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new HtmlMinimizerPlugin({
        minimizerOptions: [
          // Options for the first function (HtmlMinimizerPlugin.htmlMinifierTerser)
          {
            collapseWhitespace: true,
          },
          // Options for the second function
          {},
        ],
        minify: [
          HtmlMinimizerPlugin.htmlMinifierTerser,
          (data, minimizerOptions) => {
            const [[filename, input]] = Object.entries(data);
            // To do something
            return {
              code: `optimised code`,
              warnings: [],
              errors: [],
            };
          },
        ],
      }),
    ],
  },
};

minimizerOptions

类型

type minimizerOptions =
  | {
      [key: string]: any;
    }
  | Array<{
      [key: string]: any;
    }>;

默认值

{
caseSensitive: true,
collapseWhitespace: true,
conservativeCollapse: true,
keepClosingSlash: true,
minifyCSS: true,
minifyJS: true,
removeComments: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
}

Html-minifier-terser 优化选项

object

将相同的选项应用于默认或自定义的 minify 函数。

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new HtmlMinimizerPlugin({
        minimizerOptions: {
          collapseWhitespace: false,
        },
      }),
    ],
  },
};

array

minify 数组中的函数索引对应于 minimizerOptions 数组中具有相同索引的选项对象。如果您将 minimizerOptions 用作对象,则所有 minify 函数都将接受它。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new HtmlMinimizerPlugin({
        minimizerOptions: [
          // Options for the first function (HtmlMinimizerPlugin.htmlMinifierTerser)
          {
            collapseWhitespace: true,
          },
          // Options for the second function
          {},
        ],
        minify: [
          HtmlMinimizerPlugin.htmlMinifierTerser,
          (data, minimizerOptions) => {
            const [[filename, input]] = Object.entries(data);
            // To do something
            return {
              code: `optimised code`,
              warnings: [],
              errors: [],
            };
          },
        ],
      }),
    ],
  },
};

示例

swc/html

可用的 options

HTML 文档

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

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        type: "asset/resource",
      },
    ],
  },
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          context: path.resolve(__dirname, "dist"),
          from: "./src/*.html",
        },
      ],
    }),
  ],
  optimization: {
    minimize: true,
    minimizer: [
      new HtmlMinimizerPlugin({
        minify: HtmlMinimizerPlugin.swcMinify,
        minimizerOptions: {
          // Options - https://github.com/swc-project/bindings/blob/main/packages/html/index.ts#L5
        },
      }),
    ],
  },
};

HTML 片段

将此用于部分 HTML 文件(例如,在 <template></template> 标签或 HTML 字符串内部)。

const HtmlMinimizerPlugin = require("html-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const path = require("path");

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        type: "asset/resource",
      },
    ],
  },
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          context: path.resolve(__dirname, "dist"),
          from: "./src/*.html",
        },
      ],
    }),
  ],
  optimization: {
    minimize: true,
    minimizer: [
      new HtmlMinimizerPlugin({
        test: /\.template\.html$/i,
        minify: HtmlMinimizerPlugin.swcMinifyFragment,
        minimizerOptions: {
          // Options - https://github.com/swc-project/bindings/blob/main/packages/html/index.ts#L38
        },
      }),
    ],
  },
};

@minify-html/node

可用的 options

HTML 文档

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

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        type: "asset/resource",
      },
    ],
  },
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          context: path.resolve(__dirname, "dist"),
          from: "./src/*.html",
        },
      ],
    }),
  ],
  optimization: {
    minimize: true,
    minimizer: [
      new HtmlMinimizerPlugin({
        minify: HtmlMinimizerPlugin.minifyHtmlNode,
        minimizerOptions: {
          // Options - https://github.com/wilsonzlin/minify-html#minification
        },
      }),
    ],
  },
};

您可以使用多个 HtmlMinimizerPlugin 插件,使用不同的 minify 函数压缩不同的文件。

贡献

我们欢迎所有贡献!如果您是新用户,请在提交问题或拉取请求之前花一些时间阅读我们的贡献指南。

CONTRIBUTING

许可证

MIT

HtmlWebpackPlugin

HtmlWebpackPlugin 简化了 HTML 文件的创建,以便为您的 webpack 包提供服务。这对于文件名中包含哈希值且每次编译都会更改的 webpack 包特别有用。您可以让插件为您生成 HTML 文件,使用 lodash 模板提供您自己的模板,或者使用您自己的 加载器

安装

npm install --save-dev html-webpack-plugin

基本用法

该插件将为您生成一个 HTML5 文件,其中使用 script 标签在 body 中包含您的所有 webpack 包。按如下方式将插件添加到您的 webpack 配置中

const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

module.exports = {
  entry: 'index.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'index_bundle.js',
  },
  plugins: [new HtmlWebpackPlugin()],
};

这将生成一个包含以下内容的 dist/index.html 文件

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>webpack App</title>
  </head>
  <body>
    <script src="index_bundle.js"></script>
  </body>
</html>

如果您有多个 webpack 入口点,它们都将以 <script> 标签的形式包含在生成的 HTML 中。

如果 webpack 的输出中包含任何 CSS 资产(例如,使用 MiniCssExtractPlugin 提取的 CSS),那么这些资产将以 <link> 标签的形式包含在生成的 HTML 的 <head> 元素中。

配置

有关所有配置选项,请参阅插件文档

第三方插件

该插件支持附加组件。有关列表,请参阅文档

IgnorePlugin

IgnorePlugin 防止为匹配正则表达式或过滤函数的 importrequire 调用生成模块。

使用正则表达式

  • resourceRegExp:用于测试资源的正则表达式。
  • contextRegExp:(可选)用于测试上下文(目录)的正则表达式。
new webpack.IgnorePlugin({ resourceRegExp, contextRegExp });

使用过滤函数

  • checkResource (resource, context) 一个过滤函数,接收 resourcecontext 作为参数,必须返回布尔值。
new webpack.IgnorePlugin({
  checkResource(resource) {
    // do something with resource
    return true | false;
  },
});

忽略 Moment 区域设置的示例

moment 2.18 开始,所有区域设置都与核心库捆绑在一起(参见此 GitHub Issue)。

传递给 IgnorePluginresourceRegExp 参数不是根据解析的文件名或被导入或引用的绝对模块名进行测试,而是根据源代码中导入发生位置传递给 requireimport字符串进行测试。例如,如果您尝试排除 node_modules/moment/locale/*.js,这将不起作用

-new webpack.IgnorePlugin({ resourceRegExp: /moment\/locale\// });

相反,因为 moment 使用此代码导入

require('./locale/' + name);

...您的第一个正则表达式必须匹配 './locale/' 字符串。第二个 contextRegExp 参数用于选择发生导入的特定目录。以下将导致这些区域设置文件被忽略

new webpack.IgnorePlugin({
  resourceRegExp: /^\.\/locale$/,
  contextRegExp: /moment$/,
});

...这意味着“任何来自以 'moment' 结尾的目录且匹配 './locale'require 语句都将被忽略。”

ImageMinimizerWebpackPlugin

一个用于 webpack 的插件和加载器,用于使用 imagemin 优化(压缩)所有图像。无需担心图像大小,现在它们总是被优化/压缩。

npm node tests cover discussion size

入门

此插件可以使用四种不同的工具来优化或生成图像

  • imagemin - 默认优化您的图像,因为它稳定且适用于所有类型的图像
  • 已废弃 squoosh - 在实验模式下支持 .jpg.jpeg.png.webp.avif 文件类型。
  • sharp - 高性能 Node.js 图像处理模块,调整大小和压缩 JPEG、PNG、WebP、AVIF 和 TIFF 图像最快的模块。使用 libvips 库。
  • svgo - 用于优化 SVG 矢量图形文件的工具。仅支持 SVG 文件缩小。

[!警告]

默认情况下,我们不会安装任何额外的包。

安装优化/生成工具

首先,您需要安装 image-minimizer-webpack-plugin 以及图像优化器或生成器

npm install image-minimizer-webpack-plugin imagemin --save-dev

[!警告]

imagemin 使用插件来优化或生成图像,因此您也需要安装这些插件。

npm install image-minimizer-webpack-plugin @squoosh/lib --save-dev
npm install image-minimizer-webpack-plugin sharp --save-dev
npm install image-minimizer-webpack-plugin svgo --save-dev

图像可以通过两种模式进行优化

  1. 无损(不损失质量)。
  2. 有损(有一定质量损失)。

使用 imagemin 优化

[!注意]

探索可用选项,为您的用例找到最佳结果。

推荐用于无损优化的 imagemin 插件

npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo --save-dev

推荐用于有损优化的 imagemin 插件

npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo --save-dev

对于 imagemin-svgo v9.0.0+,您需要使用官方的 SVGO 配置

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        type: "asset",
      },
    ],
  },
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            // Lossless optimization with custom option
            // Feel free to experiment with options for better results
            plugins: [
              ["gifsicle", { interlaced: true }],
              ["jpegtran", { progressive: true }],
              ["optipng", { optimizationLevel: 5 }],
              // SVGO configuration here https://github.com/svg/svgo#configuration
              [
                "svgo",
                {
                  plugins: [
                    {
                      name: "preset-default",
                      params: {
                        overrides: {
                          removeViewBox: false,
                          addAttributesToSVGElement: {
                            params: {
                              attributes: [
                                { xmlns: "http://www.w3.org/2000/svg" },
                              ],
                            },
                          },
                        },
                      },
                    },
                  ],
                },
              ],
            ],
          },
        },
      }),
    ],
  },
};

已废弃 使用 squoosh 优化

npm install @squoosh/lib --save-dev

推荐用于有损优化的 @squoosh/lib 选项

对于有损优化,我们建议使用 @squoosh/lib 包的默认设置。每个选项的默认值和支持的文件类型可以在 codecs 目录下的 codecs.ts 文件中找到。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  module: {
    rules: [
      // You need this, if you are using `import file from "file.ext"`; not needed for `new URL(...)` syntax
      {
        test: /\.(jpe?g|png)$/i,
        type: "asset",
      },
    ],
  },
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.squooshMinify,
          options: {
            // Your options for `squoosh` here
          },
        },
      }),
    ],
  },
};

推荐用于无损优化的 squoosh 选项

对于无损优化,我们建议使用 minimizer.options.encodeOptions 中列出的以下选项。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  module: {
    rules: [
      // You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
      {
        test: /\.(jpe?g|png)$/i,
        type: "asset",
      },
    ],
  },
  optimization: {
    minimizer: [
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.squooshMinify,
          options: {
            encodeOptions: {
              mozjpeg: {
                // That setting might be close to lossless, but it’s not guaranteed
                // See https://github.com/GoogleChromeLabs/squoosh/issues/85
                quality: 100,
              },
              webp: {
                lossless: 1,
              },
              avif: {
                // See https://github.com/GoogleChromeLabs/squoosh/blob/dev/codecs/avif/enc/README.md
                cqLevel: 0,
              },
            },
          },
        },
      }),
    ],
  },
};

使用 sharp 优化

npm install sharp --save-dev

推荐用于有损优化的 sharp 选项

对于有损优化,我们建议使用 sharp 包的默认设置。每个选项的默认值和支持的文件类型可以在 sharp 文档中找到。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  module: {
    rules: [
      // You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
      {
        test: /\.(jpe?g|png)$/i,
        type: "asset",
      },
    ],
  },
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.sharpMinify,
          options: {
            encodeOptions: {
              // Customize your `sharp` options here
              // See https://sharp.pixelplumbing.com/api-output
            },
          },
        },
      }),
    ],
  },
};

推荐用于无损优化的 sharp 选项

对于无损优化,我们建议使用 minimizer.options.encodeOptions 中列出的以下选项。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  module: {
    rules: [
      // You need this, if you are using `import file from "file.ext"`. Not needed for `new URL(...)` syntax
      {
        test: /\.(jpe?g|png)$/i,
        type: "asset",
      },
    ],
  },
  optimization: {
    minimizer: [
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.sharpMinify,
          options: {
            encodeOptions: {
              jpeg: {
                // https://sharp.pixelplumbing.com/api-output#jpeg
                quality: 100,
              },
              webp: {
                // https://sharp.pixelplumbing.com/api-output#webp
                lossless: true,
              },
              avif: {
                // https://sharp.pixelplumbing.com/api-output#avif
                lossless: true,
              },

              // PNG by default sets the quality to 100%, which is same as lossless
              // https://sharp.pixelplumbing.com/api-output#png
              png: {},

              // GIF does not support lossless compression at all
              // https://sharp.pixelplumbing.com/api-output#gif
              gif: {},
            },
          },
        },
      }),
    ],
  },
};

使用 svgo 优化

npm install svgo --save-dev

推荐用于优化的 svgo 选项

对于 SVG 优化,我们建议使用 minimizer.options.encodeOptions 中列出的以下选项。插件的默认值可以在 svgo 插件源代码中找到。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  module: {
    rules: [
      // You need this, if you are using `import file from "file.ext"`. Not needed for `new URL(...)` syntax
      {
        test: /\.(svg)$/i,
        type: "asset",
      },
    ],
  },
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.svgoMinify,
          options: {
            encodeOptions: {
              // Pass over SVGs multiple times to ensure all optimizations are applied (False by default)
              multipass: true,
              plugins: [
                // Built-in plugin preset enabled by default
                // See: https://github.com/svg/svgo#default-preset
                "preset-default",
              ],
            },
          },
        },
      }),
    ],
  },
};

高级设置

  • 如果您想单独使用 loaderplugin,请参阅以下部分,但不推荐这样做。

  • 默认情况下,插件会配置 loader(如果您想禁用此行为,请使用 loader 选项),因此,当您使用插件配置时,不应设置独立加载器。

  • 加载器使用选项来优化或生成图像,因此通过 data URI(即 data:)内联的图像也将被优化或生成,非内联图像也将被优化。

查询参数(目前仅支持 squooshsharp

该插件支持以下查询参数

  • width/w - 允许您设置图像宽度

  • height/h - 允许您设置图像高度

  • as - 用于指定 preset 选项

    目前仅支持 sharp

  • unit/u - 可以是 pxpercent,并允许您按图像大小的百分比调整大小。

示例

const myImage1 = new URL("image.png?width=150&height=120", import.meta.url);
const myImage2 = new URL("image.png?w=150&h=120", import.meta.url);
// You can omit one of the parameters to auto-scale
const myImage3 = new URL("image.png?w=150", import.meta.url);
// It works with the `preset` query parameter
const myImage4 = new URL("image.png?as=webp&w=150&h=120", import.meta.url);
// You can use `auto` to reset `width` or `height` from the `preset` option
const myImage5 = new URL("image.png?as=webp&w=150&h=auto", import.meta.url);
// You can use `unit` to get the non-retina resize of images that are retina sized
const myImage6 = new URL("image.png?width=50&unit=percent", import.meta.url);
.class {
  background: url("./image.png?width=150&height=120");
}
<picture>
  <source srcset="photo.jpg?as=avif&width=150&height=120" type="image/avif" />
  <source srcset="photo.jpg?as=webp&width=150&height=120" type="image/webp" />
  <img src="photo.jpg?width=150&height=120" alt="photo" />
</picture>

[!注意]

您需要设置 avifwebp 预设,请参阅 webp 示例

独立加载器

文档:使用加载器.

在您的 webpack.config.js 中,添加 ImageMinimizerPlugin.loader 并指定资产模块选项(如果您在 import 中使用图像)

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  module: {
    rules: [
      // You need this, if you are using `import file from "file.ext"`. Not needed for `new URL(...)` syntax
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        type: "asset",
      },
      // We recommend using only for the "production" mode
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        enforce: "pre",
        use: [
          {
            loader: ImageMinimizerPlugin.loader,
            options: {
              minimizer: {
                implementation: ImageMinimizerPlugin.imageminMinify,
                options: {
                  plugins: [
                    "imagemin-gifsicle",
                    "imagemin-mozjpeg",
                    "imagemin-pngquant",
                    "imagemin-svgo",
                  ],
                },
              },
            },
          },
        ],
      },
    ],
  },
};

独立插件

文档:使用插件.

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  module: {
    rules: [
      // You need this, if you are using `import file from "file.ext"`. Not needed for `new URL(...)` syntax
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        type: "asset",
      },
    ],
  },
  optimization: {
    minimizer: [
      // Extend default minimizer, i.e. `terser-webpack-plugin` for JS
      "...",
      // We recommend using only for the "production" mode
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
        loader: false, // Disable the `loader`
      }),
    ],
  },
};

插件选项

test

类型

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

默认值:/\.(jpe?g\|png\|gif\|tif\|webp\|svg\|avif)\$/i

用于匹配文件的测试。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        test: /\.(jpe?g|png|gif|svg)$/i,
      }),
    ],
  },
};

include

类型

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

默认值:undefined

要包含的文件。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

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

exclude

类型

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

默认值:undefined

要排除的文件。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

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

minimizer

类型

type minimizer =
  | {
      implementation: (
        original: {
          filename: string;
          data: Buffer;
          warnings: Array<Error>;
          errors: Array<Error>;
          info: import("webpack").AssetInfo;
        },
        options?:
          | {
              [key: string]: any;
            }
          | undefined,
      ) => Promise<{
        filename: string;
        data: Buffer;
        warnings: Array<Error>;
        errors: Array<Error>;
        info: import("webpack").AssetInfo;
      }> & {
        setup?: (() => void) | undefined;
        teardown?: (() => void) | undefined;
      };
      options?:
        | {
            [key: string]: any;
          }
        | undefined;
      filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
      filename?:
        | string
        | ((
            pathData: {
              filename?: string | undefined;
            },
            assetInfo?: import("webpack").AssetInfo | undefined,
          ) => string)
        | undefined;
    }
  | Array<{
      implementation: (
        original: {
          filename: string;
          data: Buffer;
          warnings: Array<Error>;
          errors: Array<Error>;
          info: import("webpack").AssetInfo;
        },
        options?:
          | {
              [key: string]: any;
            }
          | undefined,
      ) => Promise<{
        filename: string;
        data: Buffer;
        warnings: Array<Error>;
        errors: Array<Error>;
        info: import("webpack").AssetInfo;
      }> & {
        setup?: (() => void) | undefined;
        teardown?: (() => void) | undefined;
      };
      options?:
        | {
            [key: string]: any;
          }
        | undefined;
      filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
      filename?:
        | string
        | ((
            pathData: {
              filename?: string | undefined;
            },
            assetInfo?: import("webpack").AssetInfo | undefined,
          ) => string)
        | undefined;
    }>;

默认值:undefined

允许设置默认的缩小函数。

可用的缩小器

  • ImageMinimizerPlugin.imageminMinify
  • 已废弃 ImageMinimizerPlugin.squooshMinify
  • ImageMinimizerPlugin.sharpMinify
  • ImageMinimizerPlugin.svgoMinify

imagemin 的单个缩小器示例

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          // Implementation
          implementation: ImageMinimizerPlugin.imageminMinify,
          // Options
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
      }),
    ],
  },
};

更多信息和示例请见此处

已废弃 squoosh 的单个缩小器示例

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          // Implementation
          implementation: ImageMinimizerPlugin.squooshMinify,
          // Options
          options: {
            encodeOptions: {
              mozjpeg: {
                quality: 90,
              },
            },
          },
        },
      }),
    ],
  },
};

更多信息和示例请见此处

sharp 的单个缩小器示例

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          // Implementation
          implementation: ImageMinimizerPlugin.sharpMinify,
          // Options
          options: {
            encodeOptions: {
              jpeg: {
                quality: 90,
              },
            },
          },
        },
      }),
    ],
  },
};

更多信息和示例请见此处

用户自定义实现的单个缩小器示例

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: async (original, options) => {
            const inputExt = path.extname(original.filename).toLowerCase();

            if (inputExt !== ".xxx") {
              // Return `null` if the implementation does not support this file type
              return null;
            }

            let result;

            try {
              result = await minifyAndReturnBuffer(original.data);
            } catch (error) {
              // Store error and return `null` if there was an error
              original.errors.push(error);
              return null;
            }

            return {
              filename: original.filename,
              data: result,
              warnings: [...original.warnings],
              errors: [...original.errors],
              info: {
                ...original.info,
                // Please always set it to prevent double minification
                minimized: true,
                // Optional
                minimizedBy: ["custom-name-of-minimication"],
              },
            };
          },
          options: {
            // Custom options
          },
        },
      }),
    ],
  },
};

多个缩小器示例

允许设置多个缩小器。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: [
          {
            // `sharp` will handle all bitmap formats (JPG, PNG, GIF, ...)
            implementation: ImageMinimizerPlugin.sharpMinify,

            // exclude SVG if implementation support it. Not required for `sharp`.
            // filter: (source, sourcePath) => !(/\.(svg)$/i.test(sourcePath)),

            options: {
              encodeOptions: {
                // Your options for `sharp`
                // https://sharp.pixelplumbing.com/api-output
              },
            },
          },
          {
            // `svgo` will handle vector images (SVG)
            implementation: ImageMinimizerPlugin.svgoMinify,
            options: {
              encodeOptions: {
                // Pass over SVGs multiple times to ensure all optimizations are applied. False by default
                multipass: true,
                plugins: [
                  // set of built-in plugins enabled by default
                  // see: https://github.com/svg/svgo#default-preset
                  "preset-default",
                ],
              },
            },
          },
        ],
      }),
    ],
  },
};

缩小器选项

implementation

类型

type implementation = (
  original: {
    filename: string;
    data: Buffer;
    warnings: Array<Error>;
    errors: Array<Error>;
    info: import("webpack").AssetInfo;
  },
  options?: BasicTransformerOptions<T>,
) => Promise<{
  filename: string;
  data: Buffer;
  warnings: Array<Error>;
  errors: Array<Error>;
  info: import("webpack").AssetInfo;
}> & {
  setup?: (() => void) | undefined;
  teardown?: (() => void) | undefined;
};

默认值:undefined

配置默认的 implementation

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          // Implementation
          implementation: ImageMinimizerPlugin.sharpMinify,
          // Options
          options: {
            encodeOptions: {
              jpeg: {
                quality: 90,
              },
            },
          },
        },
      }),
    ],
  },
};
options

类型

type options = {
  [key: string]: any;
};

默认值:undefined

implementation 选项的选项(即 imagemin/squoosh/sharp/自定义实现的选项)。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.sharpMinify,
          // Options
          options: {
            encodeOptions: {
              jpeg: {
                quality: 90,
              },
            },
          },
        },
      }),
    ],
  },
};
filter

类型

type filter = (source: Buffer, sourcePath: string) => boolean | undefined;

默认值:() => true

允许过滤要优化或生成的图像。

返回 true 以处理(优化或生成)图像,或返回 false 以跳过。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          filter: (source, sourcePath) => {
            // The `source` argument is a `Buffer` of source file
            // The `sourcePath` argument is an absolute path to source
            if (source.byteLength < 8192) {
              return false;
            }

            return true;
          },
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
      }),
    ],
  },
};
filename

类型

type filename =
  | string
  | ((
      pathData: {
        filename?: string | undefined;
      },
      assetInfo?: import("webpack").AssetInfo | undefined,
    ) => string)
  | undefined;

默认值:undefined

允许设置文件名。支持的值请参见 webpack 模板字符串(有关支持的模式,请参见 File-level 部分)。

我们还支持 [width][height] 占位符(仅在使用 sharpsquoosh 时)。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          filename: "optimized-[name][ext]",
          implementation: ImageMinimizerPlugin.sharpMinify,
          // Options
          options: {
            encodeOptions: {
              jpeg: {
                quality: 90,
              },
            },
          },
        },
      }),
    ],
  },
};

function 用法示例

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          filename: () => "optimized-[name][ext]",
          implementation: ImageMinimizerPlugin.sharpMinify,
          // Options
          options: {
            encodeOptions: {
              jpeg: {
                quality: 90,
              },
            },
          },
        },
      }),
    ],
  },
};

generator

类型

type generator = Array<{
  implementation: (
    original: {
      filename: string;
      data: Buffer;
      warnings: Array<Error>;
      errors: Array<Error>;
      info: import("webpack").AssetInfo;
    },
    options?:
      | {
          [key: string]: any;
        }
      | undefined,
  ) => Promise<{
    filename: string;
    data: Buffer;
    warnings: Array<Error>;
    errors: Array<Error>;
    info: import("webpack").AssetInfo;
  }> & {
    setup?: (() => void) | undefined;
    teardown?: (() => void) | undefined;
  };
  options?:
    | {
        [key: string]: any;
      }
    | undefined;
  filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
  filename?:
    | string
    | ((
        pathData: {
          filename?: string | undefined;
        },
        assetInfo?: import("webpack").AssetInfo | undefined,
      ) => string)
    | undefined;
  preset?: string | undefined;
  type?: "import" | "asset" | undefined;
}>;

默认值:undefined

允许设置默认图像生成器。当您想从原始图像生成 webpavif 等附加格式时,这非常有用。

[!警告]

如果图像未找到生成器(即在查询参数中未找到 ?as=webp),将使用 minimizer 选项。因此,建议配置生成器输出优化后的图像。

[!警告]

如果您禁用 loader(即将 loader 选项设置为 false),此选项将不起作用。

可用的生成器

  • ImageMinimizerPlugin.imageminGenerate
  • 已废弃 ImageMinimizerPlugin.squooshGenerate
  • ImageMinimizerPlugin.sharpGenerate

imagemin 的生成器示例

webp 生成器示例

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            // You can apply generator using `?as=webp`
            // You can use any name and provide more options
            preset: "webp",
            implementation: ImageMinimizerPlugin.imageminGenerate,
            options: {
              // Please specify only one plugin here, multiple plugins will not work
              plugins: ["imagemin-webp"],
            },
          },
        ],
      }),
    ],
  },
};

已废弃 squoosh 的生成器示例

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            // You can apply generator using `?as=webp`, you can use any name and provide more options
            preset: "webp",
            implementation: ImageMinimizerPlugin.squooshGenerate,
            options: {
              encodeOptions: {
                // Please specify only one codec here, multiple codecs will not work
                webp: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};

sharp 的生成器示例

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            // You can apply generator using `?as=webp`, you can use any name and provide more options
            preset: "webp",
            implementation: ImageMinimizerPlugin.sharpGenerate,
            options: {
              encodeOptions: {
                // Please specify only one codec here, multiple codecs will not work
                webp: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};

现在您可以使用以下方式生成新图像

// Old approach for getting URL
import webp from "./file.jpg?as=webp";

// Assets modules
console.log(new URL("./file.jpg?as=webp"));
div {
  background: url("./file.jpg?as=webp");
}

您可以在任何类型的文件中使用 ?as=webp

多个生成器示例

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            // You can apply generator using `?as=webp`, you can use any name and provide more options
            preset: "webp",
            implementation: ImageMinimizerPlugin.sharpGenerate,
            options: {
              encodeOptions: {
                webp: {
                  lossless: false,
                },
              },
            },
          },
          {
            // You can apply generator using `?as=avif`, you can use any name and provide more options
            preset: "avif",
            implementation: ImageMinimizerPlugin.sharpGenerate,
            options: {
              encodeOptions: {
                avif: {
                  lossless: false,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};

squooshsharp 生成器支持更多选项,例如您可以调整图像大小

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            // You can apply generator using `?as=webp-100-50`, you can use any name and provide more options
            preset: "webp-100-50",
            // implementation: ImageMinimizerPlugin.squooshGenerate,
            implementation: ImageMinimizerPlugin.sharpGenerate,
            options: {
              resize: {
                enabled: true,
                width: 100,
                height: 50,
              },
              encodeOptions: {
                webp: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};

您可以在 squoosh GitHub 存储库中找到更多信息。

目前仅对于 sharp,您甚至可以生成图像的非 Retina 尺寸调整版本

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            // You can apply generator using `?as=webp-1x`, you can use any name and provide more options
            preset: "webp-1x",
            implementation: ImageMinimizerPlugin.sharpGenerate,
            options: {
              resize: {
                enabled: true,
                width: 50,
                unit: "percent",
              },
              encodeOptions: {
                webp: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};

用户自定义实现的生成器示例

您可以使用自己的生成器实现。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            // You can apply generator using `?as=webp`, you can use any name and provide more options
            preset: "webp",
            implementation: async (original, options) => {
              const inputExt = path.extname(original.filename).toLowerCase();

              if (inputExt !== ".xxx") {
                // Store error and return `null` if the implementation does not support this file type
                original.errors.push(error);
                return null;
              }

              let result;

              try {
                result = await minifyAndReturnBuffer(original.data);
              } catch (error) {
                // Store error and return `null` if there was an error
                original.errors.push(error);
                return null;
              }

              return {
                filename: original.filename,
                data: result,
                warnings: [...original.warnings],
                errors: [...original.errors],
                info: {
                  ...original.info,
                  // Please always set it to prevent double minification
                  generated: true,
                  // Optional
                  generatedBy: ["custom-name-of-minification"],
                },
              };
            },
            options: {
              // Your options
            },
          },
        ],
      }),
    ],
  },
};

生成器选项

type

类型

type type = "import" | "asset" | undefined;

默认值:"import"

允许您将生成器应用于编译中的 importassets(对于复制的资产很有用)。默认情况下,生成器应用于 import/require,但有时您需要从其他插件(例如 - copy-webpack-plugin)生成新图像。如果您需要此功能,请将 type 选项设置为 asset 值。

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
        generator: [
          {
            // Apply generator for copied assets
            type: "asset",
            // You can use `ImageMinimizerPlugin.squooshGenerate`
            // You can use `ImageMinimizerPlugin.sharpGenerate`
            implementation: ImageMinimizerPlugin.imageminGenerate,
            options: {
              plugins: ["imagemin-webp"],
            },
          },
        ],
      }),
    ],
  },
  plugins: [new CopyPlugin({ patterns: ["images/**/*.png"] })],
};
preset

类型

type preset = string | undefined;

默认值:undefined

配置预设的名称,即您可以在 ?as=name 中使用它。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            preset: "name",
            // Implementation
            implementation: ImageMinimizerPlugin.sharpMinify,
            options: {
              encodeOptions: {
                jpeg: {
                  quality: 85,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};
implementation

类型

type implementation = (
  original: {
    filename: string;
    data: Buffer;
    warnings: Array<Error>;
    errors: Array<Error>;
    info: import("webpack").AssetInfo;
  },
  options?:
    | {
        [key: string]: any;
      }
    | undefined,
) => Promise<{
  filename: string;
  data: Buffer;
  warnings: Array<Error>;
  errors: Array<Error>;
  info: import("webpack").AssetInfo;
}> & {
  setup?: (() => void) | undefined;
  teardown?: (() => void) | undefined;
};

默认值:undefined

配置默认的 implementation

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            preset: "name",
            // Implementation
            implementation: ImageMinimizerPlugin.sharpMinify,
            options: {
              encodeOptions: {
                jpeg: {
                  quality: 85,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};
options

类型

type options = {
  [key: string]: any;
};

默认值:undefined

implementation 的选项(即 imagemin/squoosh/sharp/自定义实现的选项)。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            preset: "name",
            implementation: ImageMinimizerPlugin.sharpMinify,
            // Options
            options: {
              encodeOptions: {
                jpeg: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};
filter

类型

type filter = (source: Buffer, sourcePath: string) => boolean;

默认值:() => true

允许过滤要优化/生成的图像。

返回 true 以优化图像,或返回 false 以跳过。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            preset: "name",
            filter: (source, sourcePath) => {
              // The `source` argument is a `Buffer` of the source file
              // The `sourcePath` argument is an absolute path to the source
              if (source.byteLength < 8192) {
                return false;
              }

              return true;
            },
            implementation: ImageMinimizerPlugin.imageminMinify,
            options: {
              plugins: [
                "imagemin-gifsicle",
                "imagemin-mozjpeg",
                "imagemin-pngquant",
                "imagemin-svgo",
              ],
            },
          },
        ],
      }),
    ],
  },
};
filename

类型

type filename =
  | string
  | ((
      pathData: PathData,
      assetInfo?: import("webpack").AssetInfo | undefined,
    ) => string);

默认值:undefined

允许设置文件名。支持的值请参见 webpack 模板字符串File-level 部分。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            preset: "name",
            filename: "generated-[name][ext]",
            implementation: ImageMinimizerPlugin.sharpMinify,
            // Options
            options: {
              encodeOptions: {
                jpeg: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};

function 用法示例

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            preset: "name",
            filename: () => "generated-[name][ext]",
            implementation: ImageMinimizerPlugin.sharpMinify,
            // Options
            options: {
              encodeOptions: {
                jpeg: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};

severityError

类型

type severityError = string;

默认值:'error'

允许选择图像优化期间如何显示错误。

可以有以下值

  • 'off' - 抑制错误和警告
  • 'warning' - 发出警告而不是错误
  • 'error' - 发出错误

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        severityError: "warning",
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
      }),
    ],
  },
};

loader

类型

type loader = boolean;

默认值:true

自动添加内置 loader,用于优化/生成图像。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        loader: false,
        // `generator` will not work in this case
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
      }),
    ],
  },
};

concurrency

类型

type concurrency = number;

默认值:Math.max(1, os.cpus().length - 1)

一次最大并发优化进程数。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        concurrency: 3,
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
      }),
    ],
  },
};

deleteOriginalAssets

类型

type deleteOriginalAssets = boolean;

默认值:true

允许在优化后删除原始资产。

如果您为 minimizer 选项设置了 filename 选项,禁用了 loader: false 并希望保留优化和未优化的资产,请使用此选项。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        // Disable loader
        loader: false,
        // Allows to keep original asset and minimized assets with different filenames
        deleteOriginalAssets: false,
        minimizer: {
          filename: "[path][name].webp",
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
      }),
    ],
  },
};

加载器选项

minimizer

类型

type minimizer =
  | {
      implementation: (
        original: {
          filename: string;
          data: Buffer;
          warnings: Array<Error>;
          errors: Array<Error>;
          info: import("webpack").AssetInfo;
        },
        options?:
          | {
              [key: string]: any;
            }
          | undefined,
      ) => Promise<{
        filename: string;
        data: Buffer;
        warnings: Array<Error>;
        errors: Array<Error>;
        info: import("webpack").AssetInfo;
      }> & {
        setup?: (() => void) | undefined;
        teardown?: (() => void) | undefined;
      };
      options?:
        | {
            [key: string]: any;
          }
        | undefined;
      filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
      filename?:
        | string
        | ((
            pathData: {
              filename?: string | undefined;
            },
            assetInfo?: import("webpack").AssetInfo | undefined,
          ) => string)
        | undefined;
    }
  | Array<{
      implementation: (
        original: {
          filename: string;
          data: Buffer;
          warnings: Array<Error>;
          errors: Array<Error>;
          info: import("webpack").AssetInfo;
        },
        options?:
          | {
              [key: string]: any;
            }
          | undefined,
      ) => Promise<{
        filename: string;
        data: Buffer;
        warnings: Array<Error>;
        errors: Array<Error>;
        info: import("webpack").AssetInfo;
      }> & {
        setup?: (() => void) | undefined;
        teardown?: (() => void) | undefined;
      };
      options?:
        | {
            [key: string]: any;
          }
        | undefined;
      filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
      filename?:
        | string
        | ((
            pathData: {
              filename?: string | undefined;
            },
            assetInfo?: import("webpack").AssetInfo | undefined,
          ) => string)
        | undefined;
    }>;

默认值:undefined

允许设置默认缩小器。

您可以使用单个缩小器对象或其数组。

imagemin 的加载器缩小器示例

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        type: "asset",
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        loader: ImageMinimizerPlugin.loader,
        enforce: "pre",
        options: {
          minimizer: {
            implementation: ImageMinimizerPlugin.imageminMinify,
            options: {
              plugins: [
                "imagemin-gifsicle",
                "imagemin-mozjpeg",
                "imagemin-pngquant",
                "imagemin-svgo",
              ],
            },
          },
        },
      },
    ],
  },
};

更多信息和支持的选项请参阅此处

generator

类型

type generator = Array<{
  implementation: TransformerFunction<T>;
  options?: BasicTransformerOptions<T>;
  filter?: FilterFn | undefined;
  filename?: string | FilenameFn | undefined;
  preset?: string | undefined;
  type?: "import" | "asset" | undefined;
}>;

默认值:undefined

允许设置默认生成器。这对于从现有图像创建新的图像格式(例如,webp、avif 等)非常有用。

imagemin 的加载器生成器示例

以下示例演示了如何配置一个使用 imagemin 将图像转换为 webp 格式的生成器。

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        type: "asset",
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        loader: ImageMinimizerPlugin.loader,
        enforce: "pre",
        options: {
          generator: [
            {
              preset: "webp",
              implementation: ImageMinimizerPlugin.imageminGenerate,
              options: {
                plugins: ["imagemin-webp"],
              },
            },
          ],
        },
      },
    ],
  },
};

此设置将在构建过程中自动生成原始资产的 .webp 版本。更多信息和支持的选项请参阅此处

severityError

类型

type severityError = string;

默认值:'error'

允许选择图像优化期间如何显示错误。

可以有以下值

  • 'off' - 抑制错误和警告
  • 'warning' - 发出警告而不是错误
  • 'error' - 发出错误

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        type: "asset",
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        use: [
          {
            loader: ImageMinimizerPlugin.loader,
            options: {
              severityError: "warning",
              minimizerOptions: {
                plugins: ["gifsicle"],
              },
            },
          },
        ],
      },
    ],
  },
};

附加 API

imageminNormalizeConfig(config)

此函数规范化配置(将插件名称和选项转换为 Function),以便直接在 imagemin 包中使用。

const imagemin = require("imagemin");
const { imageminNormalizeConfig } = require("image-minimizer-webpack-plugin");

/*
  console.log(imageminConfig);
  =>
  {
    plugins: [Function, Function],
    pluginsMeta: [
      { name: "imagemin-jpegtran", version: "x.x.x", options: {} },
      { name: "imagemin-pngquant", version: "x.x.x", options: { quality: [0.6, 0.8] }
    ]
  }
*/

(async () => {
  const imageminConfig = await imageminNormalizeConfig({
    plugins: ["jpegtran", ["pngquant", { quality: [0.6, 0.8] }]],
  });
  const files = await imagemin(["images/*.{jpg,png}"], {
    destination: "build/images",
    plugins: imageminConfig.plugins,
  });

  console.log(files);
  // => [{data: <Buffer 89 50 4e …>, path: 'build/images/foo.jpg'}, …]
})();

示例

根据大小优化图像

您可以根据图像大小使用不同的选项(例如 progressive/interlaced/等)(例如 - 不对小图像进行渐进式转换)。

什么是渐进式图像?此处回答

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [["jpegtran", { progressive: true }]],
          },
          // Only apply this one to files equal to or over 8192 bytes
          filter: (source) => {
            if (source.byteLength >= 8192) {
              return true;
            }

            return false;
          },
        },
      }),
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [["jpegtran", { progressive: false }]],
          },
          // Only apply this one to files under 8192
          filter: (source) => {
            if (source.byteLength < 8192) {
              return true;
            }

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

优化并生成 webp 图像

您可以使用 generator 选项生成 webp 等现代图像格式以及优化后的原始图像。

  • imagemin

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
        generator: [
          {
            // You can apply generator using `?as=webp`, you can use any name and provide more options
            preset: "webp",
            implementation: ImageMinimizerPlugin.imageminGenerate,
            options: {
              plugins: ["imagemin-webp"],
            },
          },
        ],
      }),
    ],
  },
};
  • 已废弃 squoosh

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.squooshMinify,
        },
        generator: [
          {
            // You can apply generator using `?as=webp`, you can use any name and provide more options
            preset: "webp",
            implementation: ImageMinimizerPlugin.squooshGenerate,
            options: {
              encodeOptions: {
                webp: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};
  • sharp

webpack.config.js

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.sharpMinify,
        },
        generator: [
          {
            // You can apply generator using `?as=webp`, you can use any name and provide more options
            preset: "webp",
            implementation: ImageMinimizerPlugin.sharpGenerate,
            options: {
              encodeOptions: {
                webp: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};

从复制的资产生成 webp 图像

您可以使用生成器功能从使用 copy-webpack-plugin 复制的静态资产创建现代图像格式(如 webp)。

  • imagemin

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
        generator: [
          {
            type: "asset",
            implementation: ImageMinimizerPlugin.imageminGenerate,
            options: {
              plugins: ["imagemin-webp"],
            },
          },
        ],
      }),
    ],
  },
  plugins: [new CopyPlugin({ patterns: ["images/**/*.png"] })],
};
  • 已废弃 squoosh

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.squooshMinify,
        },
        generator: [
          {
            type: "asset",
            implementation: ImageMinimizerPlugin.squooshGenerate,
            options: {
              encodeOptions: {
                webp: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
  plugins: [new CopyPlugin({ patterns: ["images/**/*.png"] })],
};
  • sharp

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.sharpMinify,
        },
        generator: [
          {
            type: "asset",
            implementation: ImageMinimizerPlugin.sharpGenerate,
            options: {
              encodeOptions: {
                webp: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
  plugins: [new CopyPlugin({ patterns: ["images/**/*.png"] })],
};

贡献

我们欢迎贡献!如果您有兴趣帮助改进此插件,请花点时间阅读我们的贡献指南。

CONTRIBUTING

许可证

MIT

InstallWebpackPlugin

npm deps test coverage chat

通过 Webpack 自动安装和保存依赖项来加速开发。

仅仅为了安装一个您之前不知道需要的依赖项而 Ctrl-C 您的构建脚本和服务器效率低下。

相反,像往常一样使用 requireimport,并且在您工作时,安装将自动进行以安装和保存缺失的依赖项

$ npm install --save-dev install-webpack-plugin

用法

在您的 webpack.config.js

plugins: [
  new InstallPlugin()
],

这等同于:

plugins: [
  new InstallPlugin({
    dependencies: {
      peer: true,
    },
    packageManager: {
      type: this.getDefaultPackageManager(),
      options: {
        dev: false,
        quiet: false,
      },
    },
    prompt: true,
  });
],

选项

dependencies

类型: Object

依赖项相关选项。

peer

类型: Boolean

默认值: true

安装缺失的对等依赖项。

plugins: [
  new InstallPlugin({
    dependencies: {
      peer: true,
    }
  }),
],

packageManager

类型: 'npm' | 'yarn' | 'pnpm' | Object | Function

用于安装依赖项的包管理器。

plugins: [
  new InstallPlugin({
      packageManager: 'yarn'
    },
  }),
],

您可以为 packageManager 提供一个 Function 以使其动态化

plugins: [
  new InstallPlugin({
    packageManager: function(module, path) {
      return [
        "babel-preset-react-hmre",
        "webpack-dev-middleware",
        "webpack-hot-middleware",
      ].indexOf(module) !== -1;
    },
  }),
],

type

类型: 'npm' | 'yarn' | 'pnpm'

用于安装依赖项的包管理器名称。

options

类型: Object

包管理器相关选项。

arguments

类型: Array

提供与包管理器一起使用的自定义参数。

plugins: [
  new InstallPlugin({
      packageManager: {
        type: 'npm',
        options: {
          arguments: ['--ignore-scripts']
        }
      }
    },
  }),
],

dev

类型: Boolean

默认值: false

安装为开发依赖项。

plugins: [
  new InstallPlugin({
      packageManager: {
        type: 'npm',
        options: {
          dev: true,
        }
      }
    },
  }),
],

quiet

类型: Boolean

默认值: false

减少控制台日志输出量。

plugins: [
  new InstallPlugin({
      packageManager: {
        type: 'npm',
        options: {
          quiet: true,
        }
      }
    },
  }),
],

prompt

类型: Boolean

默认值: true

显示提示以确认安装。

plugins: [
  new InstallPlugin({
      prompt: true,
    },
  }),
],

演示

install-webpack-plugin demo

功能

  • 适用于 webpack ^v5.0.0
  • 自动安装 .babelrc 插件和预设。
  • 支持 ES5 和 ES6 模块。(例如 require, import
  • 支持命名空间包。(例如 @cycle/dom
  • 支持点分隔包。(例如 lodash.capitalize
  • 支持 CSS 导入。(例如 @import "~bootstrap"
  • 支持 webpack 加载器。(例如 babel-loader, file-loader 等)
  • 支持内联 webpack 加载器。(例如 require("bundle?lazy!./App"
  • 自动安装缺失的 peerDependencies。(例如 @cycle/core 会自动安装 rx@*
  • 支持 webpack 的 resolve.aliasresolve.root 配置。(例如 require("react") 可以别名为 react-lite

贡献

如果你尚未阅读,请花一点时间阅读我们的贡献指南。

CONTRIBUTING

内部 webpack 插件

这是 webpack 内部使用的插件列表。

内部插件类别

环境

影响编译器环境的插件。

NodeEnvironmentPlugin

webpack.node.NodeEnvironmentPlugin()

将 Node.js 风格的文件系统应用于编译器。

编译器

影响编译器的插件

MemoryCachePlugin

MemoryCachePlugin()

为编译器添加缓存,其中模块在内存中缓存。

ProgressPlugin

ProgressPlugin(handler)

挂钩到编译器以提取进度信息。handler 必须具有 function(percentage, message) 的签名。percentage 的值在 0 到 1 之间,其中 0 表示开始,1 表示结束。

RecordIdsPlugin

RecordIdsPlugin()

从记录中保存和恢复模块和 chunk ID。

入口

将入口块添加到编译中的插件。

EntryPlugin

EntryPlugin(context, entry, options)

在编译时添加一个入口块。该块名为 options.name,只包含一个模块(加上依赖项)。模块从 context(绝对路径)中的 entry 解析。

PrefetchPlugin

PrefetchPlugin(context, request)

预取 request 和依赖项以实现更并行的编译。它不会创建任何 chunk。模块从 context(绝对路径)中的 request 解析。

输出

JsonpTemplatePlugin

JsonpTemplatePlugin(options)

Chunk 被包装到 JSONP 调用中。入口块中包含加载算法。它通过添加 <script> 标签来加载 chunk。

options 是输出选项。

options.jsonpFunction 是 JSONP 函数。

options.publicPath 用作加载 chunk 的路径。

options.chunkFilename 是期望 chunk 所在的文件名。

NodeTemplatePlugin

node/NodeTemplatePlugin(options)

Chunk 被包装到导出捆绑模块的 Node.js 模块中。入口块通过 require 它们来加载 chunk。

options 是输出选项。

options.chunkFilename 是期望 chunk 所在的文件名。

LibraryTemplatePlugin

LibraryTemplatePlugin(name, target)

入口块被装饰以形成类型为 type 的库 name

WebWorkerTemplatePlugin

webworker/WebWorkerTemplatePlugin(options)

Chunk 通过 importScripts 加载。其他方面与 JsonpTemplatePlugin 类似。

options 是输出选项。

EvalDevToolModulePlugin

通过将每个模块包装在带有 // @sourceURL 注释的 eval 中来装饰模块模板。

SourceMapDevToolPlugin

SourceMapDevToolPlugin(sourceMapFilename, sourceMappingURLComment, moduleFilenameTemplate, fallbackModuleFilenameTemplate)

通过为每个 chunk 生成 SourceMap 来装饰模板。

sourceMapFilename 是 SourceMap 的文件名模板。[hash][name][id][file][filebase] 将被替换。如果此参数缺失,SourceMap 将作为 DataUrl 内联。

HotModuleReplacementPlugin

HotModuleReplacementPlugin(options)

添加对模块热替换的支持。装饰模板以添加运行时代码。添加 module.hot API。

options.hotUpdateChunkFilename 热更新 chunk 的文件名。

options.hotUpdateMainFilename 热更新清单的文件名。

options.hotUpdateFunction 热更新的 JSON 函数名。

源码

影响模块源代码的插件。

APIPlugin

使 webpack_public_path、webpack_require、webpack_modules 和 webpack_chunk_load 可访问。确保 require.valueOfrequire.onError 不被其他插件处理。

CompatibilityPlugin

目前无用。确保与其他模块加载器的兼容性。

ConstPlugin

尝试评估 if (...) 语句和三元表达式中的表达式,并用 true/false 替换它们,以便利用解析器触发的钩子进一步消除死分支。

生产模式下有多个关于死分支的优化

  • Terser 执行的优化
  • 由 webpack 执行的优化

Webpack 会尝试评估条件语句。如果成功,则删除死分支。除非编译器知道,否则 Webpack 无法进行常量折叠。例如

import { calculateTax } from './tax';

const FOO = 1;
if (FOO === 0) {
  // dead branch
  calculateTax();
}

在上面的示例中,webpack 无法修剪分支,但 Terser 可以。但是,如果使用 DefinePlugin 定义了 FOO,webpack 将会成功。

值得一提的是,import { calculateTax } from './tax'; 也会被修剪,因为 calculateTax() 调用位于死分支中并被消除。

ProvidePlugin

ProvidePlugin(name, request)

如果模块中使用 name,它将由 require(<request>) 加载的模块填充。

NodeStuffPlugin

NodeStuffPlugin(options, context)

提供通常在 Node.js 模块中可用的内容。

它还确保如果您使用 module,它会填充一些 Node.js 的内容。

RequireJsStuffPlugin

提供通常在 require.js 中可用的内容。

require[js].config 已删除。require.version0.0.0requirejs.onError 映射到 require.onError

NodeSourcePlugin

node/NodeSourcePlugin(options)

此模块添加了在非 Node.js 环境中不可用的 Node.js 内容。

如果使用,它会为 processconsoleBufferglobal 添加 polyfills。它还会绑定内置的 Node.js 替换模块。

NodeTargetPlugin

node/NodeTargetPlugin()

如果您在 Node.js 环境中运行捆绑包,则应使用此插件。

它确保即使捆绑后,原生模块也正确加载。

AMDPlugin

dependencies/AMDPlugin(options)

为模块提供 AMD 风格的 definerequire。此外,将 require.amddefine.amd 和 webpack_amd_options## 绑定到作为参数传递的 options

CommonJsPlugin

dependencies/CommonJsPlugin

为模块提供 CommonJS 风格的 require

RequireContextPlugin

dependencies/RequireContextPlugin(modulesDirectories, extensions)

提供 require.context。参数 modulesDirectoriesextensions 用于查找文件的替代请求。提供与您提供给解析器的相同数组很有用。

RequireEnsurePlugin

dependencies/RequireEnsurePlugin()

提供 require.ensure

RequireIncludePlugin

dependencies/RequireIncludePlugin()

提供 require.include

DefinePlugin

DefinePlugin(definitions)

为标识符定义常量。

definitions 是一个对象。

优化

请注意,webpack.optimize 命名空间下的所有插件仅应在 mode 设置为 'none' 时使用。否则,您可能会遇到插件被应用两次的问题。

LimitChunkCountPlugin

optimize/LimitChunkCountPlugin(options)

合并块以限制块计数低于 options.maxChunks

每个 chunk 的开销由 options.chunkOverhead 提供,或默认为 10000。入口 chunk 的大小乘以 options.entryChunkMultiplicator(或 10)。

优先合并那些能最大程度减少总大小的 chunk。如果多个组合相等,则最小合并大小胜出。

MergeDuplicateChunksPlugin

optimize/MergeDuplicateChunksPlugin()

包含相同模块的 chunk 将被合并。

RemoveEmptyChunksPlugin

optimize/RemoveEmptyChunksPlugin()

包含在每个父 chunk 中的模块将从该 chunk 中移除。

MinChunkSizePlugin

optimize/MinChunkSizePlugin(minChunkSize)

合并 chunk,直到每个 chunk 的最小大小达到 minChunkSize

ModuleConcatenationPlugin

有关详细信息,请参阅ModuleConcatenationPlugin 页面

FlagIncludedChunksPlugin

optimize/FlagIncludedChunksPlugin()

添加 chunk 中包含的 chunk ID。这消除了不必要的 chunk 加载。

RealContentHashPlugin

optimize/RealContentHashPlugin()

optimization.realContentHash 选项启用时,webpack 将在内部将 RealContentHashPlugin 应用于编译器。

钩子

RealContentHashPlugin 提供了一个 updateHash 5.8.0+ 钩子,用于自定义哈希更新

const webpack = require('webpack');
const RealContentHashPlugin = webpack.optimize.RealContentHashPlugin;
// ...
compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
  const hooks = RealContentHashPlugin.getCompilationHooks(compilation);
  hooks.updateHash.tap('MyPlugin', (content, oldHash) => {
    // you can calculate the hash here as you wish
  });
});

JsonMinimizerWebpackPlugin

npm node tests cover discussion size

此插件使用 JSON.stringify() 在构建过程中缩小您的 JSON 文件。

入门

首先,您需要安装 json-minimizer-webpack-plugin

npm install json-minimizer-webpack-plugin --save-dev

yarn add -D json-minimizer-webpack-plugin

pnpm add -D json-minimizer-webpack-plugin

然后将插件添加到你的 webpack 配置中。例如:

webpack.config.js

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

module.exports = {
  module: {
    rules: [
      {
        test: /\.json$/i,
        type: "asset/resource",
      },
    ],
  },
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          context: path.resolve(__dirname, "dist"),
          from: "./src/*.json",
        },
      ],
    }),
  ],
  optimization: {
    minimize: true,
    minimizer: [
      // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
      // `...`
      new JsonMinimizerPlugin(),
    ],
  },
};

最后,使用你通常使用的方法运行 webpack(例如,通过 CLI 或 npm 脚本)。

选项

test

类型

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

默认值:/\.json(\?.*)?$/i

用于匹配文件的测试。

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new JsonMinimizerPlugin({
        test: /\.foo\.json/i,
      }),
    ],
  },
};

include

类型

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

默认值:undefined

要包含以进行最小化的文件。

webpack.config.js

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

exclude

类型

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

默认值:undefined

要从最小化中排除的文件。

webpack.config.js

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

minimizerOptions

类型

type minimizerOptions = {
  space?: null | string | number;
  replacer?: null | Function | Array<string | number>;
};

默认值:{ replacer: null, space: null }

JSON.stringify() 选项

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new JsonMinimizerPlugin({
        minimizerOptions: {
          space: "\t",
        },
      }),
    ],
  },
};

贡献

我们欢迎所有贡献!如果您是新用户,请在提交问题或拉取请求之前花一些时间阅读我们的贡献指南。

CONTRIBUTING

许可证

MIT

LimitChunkCountPlugin

在编写代码时,您可能已经添加了许多代码拆分点以按需加载内容。编译后您可能会注意到某些 chunk 太小,从而产生更大的 HTTP 开销。LimitChunkCountPlugin 可以通过合并您的 chunk 来后处理它们。

new webpack.optimize.LimitChunkCountPlugin({
  // Options...
});

选项

支持以下选项

maxChunks

数字

使用大于或等于 1 的值来限制最大 chunk 数量。使用 1 将防止添加任何额外的 chunk,因为入口/主 chunk 也包含在计数中。

webpack.config.js

const webpack = require('webpack');
module.exports = {
  // ...
  plugins: [
    new webpack.optimize.LimitChunkCountPlugin({
      maxChunks: 5,
    }),
  ],
};

minChunkSize

将 chunk 大小保持在指定限制之上已不再是此插件的功能。请改用 MinChunkSizePlugin

通过 CLI 使用

此插件及其选项也可以通过 CLI 调用。

webpack --optimize-max-chunks 15

MinChunkSizePlugin

通过合并小于 minChunkSize 的 chunk 来使 chunk 大小保持在指定限制之上。

new webpack.optimize.MinChunkSizePlugin({
  minChunkSize: 10000, // Minimum number of characters
});

通过 CLI 使用

此插件及其选项也可以通过 CLI 调用。

webpack --optimize-min-chunk-size 10000

MiniCssExtractPlugin

npm node tests coverage discussion size

此插件将 CSS 提取到单独的文件中。它为每个包含 CSS 的 JS 文件创建一个 CSS 文件。它支持 CSS 和 SourceMap 的按需加载。

它基于 webpack v5 的新功能构建,需要 webpack 5 才能工作。

与 extract-text-webpack-plugin 相比

  • 异步加载
  • 无重复编译(性能)
  • 更易于使用
  • 专用于 CSS

入门

首先,您需要安装 mini-css-extract-plugin

npm install --save-dev mini-css-extract-plugin

yarn add -D mini-css-extract-plugin

pnpm add -D mini-css-extract-plugin

建议将 mini-css-extract-plugincss-loader 结合使用

然后将加载器和插件添加到您的 webpack 配置中。例如

style.css

body {
  background: green;
}

component.js

import "./style.css";

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

[!警告]

请注意,如果您从 webpack 入口点导入 CSS 或在 初始 chunk 中导入样式,mini-css-extract-plugin 将不会自动将此 CSS 加载到页面中。请使用 html-webpack-plugin 自动生成 link 标签,或手动在您的 index.html 文件中包含一个 <link> 标签。

[!警告]

源映射仅适用于 source-map/nosources-source-map/hidden-nosources-source-map/hidden-source-map 值,因为 CSS 仅支持带有 sourceMappingURL 注释(即 //# sourceMappingURL=style.css.map)的源映射。如果您需要将 devtool 设置为其他值,您可以使用 css-loadersourceMap: true 来为提取的 CSS 启用源映射生成。

选项

插件选项

filename

类型

type filename =
  | string
  | ((pathData: PathData, assetInfo?: AssetInfo) => string);

默认值:[name].css

此选项确定每个输出 CSS 文件的名称。

工作方式类似于 output.filename

chunkFilename

类型

type chunkFilename =
  | string
  | ((pathData: PathData, assetInfo?: AssetInfo) => string);

默认值:基于文件名

chunkFilename 指定为 function 仅在 webpack@5 中可用。

此选项确定非入口 chunk 文件的名称。

工作方式类似于 output.chunkFilename

ignoreOrder

类型

type ignoreOrder = boolean;

默认值:false

移除顺序警告。有关更多详细信息,请参阅示例

insert

类型

type insert = string | ((linkTag: HTMLLinkElement) => void);

默认值:document.head.appendChild(linkTag);

link 标签插入到给定位置,用于 非初始(异步)CSS chunk

[!警告]

仅适用于 非初始(异步) chunk。

默认情况下,mini-css-extract-plugin 会将样式(<link> 元素)附加到当前 windowdocument.head

然而,在某些情况下,可能需要更精细地控制附加目标,甚至延迟 link 元素的插入。例如,当您异步加载在 iframe 中运行的应用程序的样式时,就是这种情况。在这种情况下,insert 可以配置为函数或自定义选择器。

如果您目标是 iframe,请确保父文档具有足够的访问权限来访问框架文档并向其附加元素。

string

允许设置自定义 查询选择器。新的 <link> 元素将插入到找到的元素之后。

webpack.config.js

new MiniCssExtractPlugin({
  insert: "#some-element",
});

一个新的 <link> 标签将插入到 ID 为 some-element 的元素之后。

function

允许覆盖默认行为并在任何位置插入样式。

⚠ 请记住,此代码将在浏览器中与您的应用程序一起运行。由于并非所有浏览器都支持最新的 ECMA 特性,例如 letconstarrow function expression 等,我们建议您仅使用 ECMA 5 的特性和语法。

insert 函数被序列化为字符串并传递给插件。这意味着它将无法访问 webpack 配置模块的作用域。

webpack.config.js

new MiniCssExtractPlugin({
  insert: function (linkTag) {
    var reference = document.querySelector("#some-element");
    if (reference) {
      reference.parentNode.insertBefore(linkTag, reference);
    }
  },
});

一个新的 <link> 标签将插入到 ID 为 some-element 的元素之前。

attributes

类型

type attributes = Record<string, string>};

默认值:{}

[!警告]

仅适用于 非初始(异步) chunk。

如果定义,mini-css-extract-plugin 将在 <link> 元素上附加给定属性及其值。

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      attributes: {
        id: "target",
        "data-target": "example",
      },
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

[!注意]

它仅适用于动态加载的 CSS 块。如果您想修改 HTML 文件中的 <link> 属性,请使用 html-webpack-plugin

linkType

类型

type linkType = string | boolean;

默认值:text/css

此选项允许使用自定义链接类型加载异步块,例如 <link type="text/css" ...>

string

可能的值:text/css

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      linkType: "text/css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};
boolean

false 完全禁用链接 type 属性。

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      linkType: false,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

runtime

类型

type runtime = boolean;

默认值:true

允许启用/禁用运行时生成。CSS 仍将被提取,可用于自定义加载方法。例如,您可以使用 assets-webpack-plugin 来检索它们,然后在需要时使用您自己的运行时代码下载资产。

设置为 false 可跳过。

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      runtime: false,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

experimentalUseImportModule

类型

type experimentalUseImportModule = boolean;

默认值:undefined

如果未明确启用(即 truefalse 允许您明确控制此选项)且新 API 可用(至少需要 webpack 5.52.0),则默认启用。布尔值从版本 5.33.2 开始可用,但您需要启用 experiments.executeModule(从 webpack 5.52.0 开始不再需要)。

使用新的 webpack API 执行模块而不是子编译器,显著提高性能和内存使用。

当与 experiments.layers 结合使用时,这会在加载器选项中添加一个 layer 选项,用于指定 CSS 执行的层。

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // You don't need this for `>= 5.52.0` due to the fact that this is enabled by default
      // Required only for `>= 5.33.2 & <= 5.52.0`
      // Not available/unsafe for `<= 5.33.2`
      experimentalUseImportModule: true,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

加载器选项

publicPath

类型

type publicPath =
  | string
  | ((resourcePath: string, rootContext: string) => string);

默认值:webpackOptions.output 中的 publicPath

CSS 中像图片、文件等外部资源指定自定义公共路径。工作方式类似于 output.publicPath

string

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: "/public/path/to/",
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};
function

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: (resourcePath, context) => {
                return path.relative(path.dirname(resourcePath), context) + "/";
              },
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

emit

类型

type emit = boolean;

默认值:true

如果为 true,则发出文件(将文件写入文件系统)。如果为 false,则插件将提取 CSS 但不会发出文件。对于服务器端包,通常禁用此选项很有用。

esModule

类型

type esModule = boolean;

默认值:true

默认情况下,mini-css-extract-plugin 生成使用 ES 模块语法的 JS 模块。在某些情况下,使用 ES 模块是有益的,例如在 模块串联摇树优化 的情况下。

您可以使用以下方式启用 CommonJS 语法

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              esModule: false,
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

defaultExport

类型

type defaultExport = boolean;

默认值:false

[!注意]

此选项仅在您将 css-loader 中的 namedExport 设置为 true 时才有效

默认情况下,mini-css-extract-plugin 根据 css-loader 中的 esModulenamedExport 选项生成 JS 模块。使用 esModulenamedExport 选项将允许您更好地优化代码。如果您为 css-loader 设置 esModule: truenamedExport: truemini-css-extract-plugin生成一个命名导出。我们官方建议仅使用命名导出以获得更好的未来兼容性。但对于某些应用程序,将代码从默认导出快速重写为命名导出并不容易。

如果您需要默认导出和命名导出,可以启用此选项

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              defaultExport: true,
            },
          },
          {
            loader: "css-loader",
            options: {
              esModule: true,
              modules: {
                namedExport: true,
              },
            },
          },
        ],
      },
    ],
  },
};

示例

推荐

对于 production 构建,建议从您的 bundle 中提取 CSS,以便稍后并行加载 CSS/JS 资源。这可以通过使用 mini-css-extract-plugin 来实现,因为它会创建单独的 css 文件。对于 development 模式(包括 webpack-dev-server),您可以使用 style-loader,因为它使用多个并将 CSS 注入 DOM,工作速度更快。

重要提示:不要同时使用 style-loadermini-css-extract-plugin

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== "production";

module.exports = {
  module: {
    rules: [
      {
        // If you enable `experiments.css` or `experiments.futureDefaults`, please uncomment line below
        // type: "javascript/auto",
        test: /\.(sa|sc|c)ss$/,
        use: [
          devMode ? "style-loader" : MiniCssExtractPlugin.loader,
          "css-loader",
          "postcss-loader",
          "sass-loader",
        ],
      },
    ],
  },
  plugins: [].concat(devMode ? [] : [new MiniCssExtractPlugin()]),
};

最小示例

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // all options are optional
      filename: "[name].css",
      chunkFilename: "[id].css",
      ignoreOrder: false, // Enable to remove warnings about conflicting order
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              // you can specify a publicPath here
              // by default it uses publicPath in webpackOptions.output
              publicPath: "../",
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

CSS 模块的命名导出

⚠ 本地名称将转换为 camelCase

⚠ 不允许在 CSS 类名中使用 JavaScript 保留字。

css-loader 中的 esModulemodules.namedExport 选项应启用。

styles.css

.foo-baz {
  color: red;
}
.bar {
  color: blue;
}

index.js

import { fooBaz, bar } from "./styles.css";

console.log(fooBaz, bar);

您可以使用以下方式启用 ES 模块命名导出

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
          },
          {
            loader: "css-loader",
            options: {
              esModule: true,
              modules: {
                namedExport: true,
                localIdentName: "foo__[name]__[local]",
              },
            },
          },
        ],
      },
    ],
  },
};

publicPath 选项作为函数

您可以将 publicPath 指定为一个函数,以根据每个资源相对于项目根或上下文的位置动态确定公共路径。

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: (resourcePath, context) => {
                // publicPath is the relative path of the resource to the context
                // e.g. for ./css/admin/main.css the publicPath will be ../../
                // while for ./css/main.css the publicPath will be ../
                return path.relative(path.dirname(resourcePath), context) + "/";
              },
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

高级配置示例

此插件不应与 style-loader 在加载器链中一起使用。

以下是同时在 development 中使用 HMR 并在 production 构建中提取样式到文件的示例。

(为清晰起见,省略了加载器选项,请根据您的需要进行调整。)

如果您正在使用 webpack-dev-server,则不应使用 HotModuleReplacementPlugin 插件。webpack-dev-server 使用 hot 选项启用/禁用 HMR。

webpack.config.js

const webpack = require("webpack");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== "production";

const plugins = [
  new MiniCssExtractPlugin({
    // Options similar to the same options in webpackOptions.output
    // both options are optional
    filename: devMode ? "[name].css" : "[name].[contenthash].css",
    chunkFilename: devMode ? "[id].css" : "[id].[contenthash].css",
  }),
];
if (devMode) {
  // only enable hot in development
  plugins.push(new webpack.HotModuleReplacementPlugin());
}

module.exports = {
  plugins,
  module: {
    rules: [
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          "postcss-loader",
          "sass-loader",
        ],
      },
    ],
  },
};

热模块重载 (HMR)

[!注意]

Webpack 5 自动支持 HMR。无需配置。跳过以下内容

mini-css-extract-plugin 支持在开发中热重载实际的 CSS 文件。提供了一些选项来启用标准样式表和局部作用域 CSS 或 CSS 模块的 HMR。以下是 mini-css 用于 HMR 与 CSS 模块结合使用的示例配置。

如果您正在使用 webpack-dev-server,则不应使用 HotModuleReplacementPlugin 插件。webpack-dev-server 使用 hot 选项启用/禁用 HMR。

webpack.config.js

const webpack = require("webpack");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const plugins = [
  new MiniCssExtractPlugin({
    // Options similar to the same options in webpackOptions.output
    // both options are optional
    filename: devMode ? "[name].css" : "[name].[contenthash].css",
    chunkFilename: devMode ? "[id].css" : "[id].[contenthash].css",
  }),
];
if (devMode) {
  // only enable hot in development
  plugins.push(new webpack.HotModuleReplacementPlugin());
}

module.exports = {
  plugins,
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {},
          },
          "css-loader",
        ],
      },
    ],
  },
};

生产环境优化

要最小化输出,请使用 css-minimizer-webpack-plugin 等插件。

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
  optimization: {
    minimizer: [
      // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`).
      // Uncomment the next line o keep JS minimizers and add CSS minimizer:
      // `...`,
      new CssMinimizerPlugin(),
    ],
  },
};
  • 默认情况下,CSS 最小化在生产模式下运行。
  • 如果您想在开发模式下也运行它,请将 optimization.minimize 选项设置为 true

使用预加载或内联 CSS

运行时代码通过 <link><style> 标签检测已添加的 CSS,并避免重复加载 CSS。

  • 这在服务器端渲染 (SSR) 中注入 CSS 时可能很有用。
  • <link> 标签的 href 必须与用于加载 CSS 块的 URL 匹配。
  • data-href 属性可用于 <link><style> 元素。
  • 内联 CSS 时必须使用 data-href

将所有 CSS 提取到单个文件中

可以使用 optimization.splitChunks.cacheGroups 结合 type "css/mini-extract" 将 CSS 提取到一个 CSS 文件中。

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {
          name: "styles",
          type: "css/mini-extract",
          chunks: "all",
          enforce: true,
        },
      },
    },
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

请注意,在 Webpack 5 中,应使用 type 而不是 test,否则除了 .css 文件之外还会生成一个额外的 .js 文件。这是因为 test 不知道哪些模块应该被删除(在这种情况下,它不会检测到 .js 应该被删除)。

根据入口提取 CSS

您还可以根据 webpack 入口名称提取 CSS。如果您动态导入路由但希望根据入口打包 CSS,这将特别有用。这还可以防止 ExtractTextPlugin 曾经出现的 CSS 重复问题。

const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: {
    foo: path.resolve(__dirname, "src/foo"),
    bar: path.resolve(__dirname, "src/bar"),
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        fooStyles: {
          type: "css/mini-extract",
          name: "styles_foo",
          chunks: (chunk) => {
            return chunk.name === "foo";
          },
          enforce: true,
        },
        barStyles: {
          type: "css/mini-extract",
          name: "styles_bar",
          chunks: (chunk) => {
            return chunk.name === "bar";
          },
          enforce: true,
        },
      },
    },
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

Filename 选项作为函数

通过 filename 选项,您可以使用 chunk 数据来自定义文件名。当处理多个入口点并希望更好地控制给定入口点/chunk 的文件名时,这尤其有用。在下面的示例中,我们将使用 filename 将生成的 css 输出到不同的目录。

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: ({ chunk }) => `${chunk.name.replace("/js/", "/css/")}.css`,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

长期缓存

对于长期缓存,请使用 filename: "[contenthash].css"。可选地添加 [name]

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].[contenthash].css",
      chunkFilename: "[id].[contenthash].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

移除顺序警告

对于通过一致使用作用域或命名约定(例如 CSS 模块)来缓解 CSS 顺序问题的项目,可以通过将插件的 ignoreOrder 标志设置为 true 来禁用 CSS 顺序警告。

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      ignoreOrder: true,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

多主题

通过有条件地加载带有查询参数的不同 SCSS 变体来切换主题。

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: "./src/index.js",
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        oneOf: [
          {
            resourceQuery: "?dark",
            use: [
              MiniCssExtractPlugin.loader,
              "css-loader",
              {
                loader: "sass-loader",
                options: {
                  additionalData: `@use 'dark-theme/vars' as vars;`,
                },
              },
            ],
          },
          {
            use: [
              MiniCssExtractPlugin.loader,
              "css-loader",
              {
                loader: "sass-loader",
                options: {
                  additionalData: `@use 'light-theme/vars' as vars;`,
                },
              },
            ],
          },
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
      attributes: {
        id: "theme",
      },
    }),
  ],
};

src/index.js

import "./style.scss";

let theme = "light";
const themes = {};

themes[theme] = document.querySelector("#theme");

async function loadTheme(newTheme) {
  // eslint-disable-next-line no-console
  console.log(`CHANGE THEME - ${newTheme}`);

  const themeElement = document.querySelector("#theme");

  if (themeElement) {
    themeElement.remove();
  }

  if (themes[newTheme]) {
    // eslint-disable-next-line no-console
    console.log(`THEME ALREADY LOADED - ${newTheme}`);

    document.head.appendChild(themes[newTheme]);

    return;
  }

  if (newTheme === "dark") {
    // eslint-disable-next-line no-console
    console.log(`LOADING THEME - ${newTheme}`);

    import(/* webpackChunkName: "dark" */ "./style.scss?dark").then(() => {
      themes[newTheme] = document.querySelector("#theme");

      // eslint-disable-next-line no-console
      console.log(`LOADED - ${newTheme}`);
    });
  }
}

document.onclick = () => {
  if (theme === "light") {
    theme = "dark";
  } else {
    theme = "light";
  }

  loadTheme(theme);
};

src/dark-theme/_vars.scss

$background: black;

src/light-theme/_vars.scss

$background: white;

src/styles.scss

body {
  background-color: vars.$background;
}

public/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Document</title>
    <link id="theme" rel="stylesheet" type="text/css" href="./main.css" />
  </head>
  <body>
    <script src="./main.js"></script>
  </body>
</html>

媒体查询插件

如果您想从提取的 CSS 中提取媒体查询(这样移动用户就不再需要加载桌面或平板电脑特定的 CSS),您应该使用以下插件之一

钩子

mini-css-extract-plugin 提供了钩子以根据您的需求进行扩展。

beforeTagInsert

SyncWaterfallHook

在注入链接标签的插入代码之前调用。应返回一个字符串

MiniCssExtractPlugin.getCompilationHooks(compilation).beforeTagInsert.tap(
  "changeHref",
  (source, varNames) =>
    Template.asString([
      source,
      `${varNames.tag}.setAttribute("href", "/plugins/mini-css-extract-plugin/));`,
    ])
);

贡献

我们欢迎所有贡献!如果您是新用户,请在提交问题或拉取请求之前花一些时间阅读我们的贡献指南。

CONTRIBUTING

许可证

MIT

ModuleConcatenationPlugin

过去,webpack 打包时的一个权衡是,bundle 中的每个模块都将被封装在单独的函数闭包中。这些封装函数会使您的 JavaScript 在浏览器中执行得更慢。相比之下,Closure Compiler 和 RollupJS 等工具会将所有模块的作用域“提升”或连接到一个闭包中,从而使您的代码在浏览器中具有更快的执行时间。

此插件将在 webpack 中启用相同的串联行为。默认情况下,此插件在 生产 mode 中已启用,否则禁用。如果您需要覆盖生产 mode 优化,请将 optimization.concatenateModules 选项 设置为 false。要在其他模式下启用串联行为,您可以手动添加 ModuleConcatenationPlugin 或使用 optimization.concatenateModules 选项

new webpack.optimize.ModuleConcatenationPlugin();

这种串联行为称为“作用域提升”。

作用域提升是 ECMAScript 模块语法实现的一个特定功能。因此,webpack 可能会根据您使用的模块类型以及 其他条件 回退到正常的打包方式。

优化跳过

正如文章所解释的,webpack 试图实现部分作用域提升。它会将模块合并到单个作用域中,但并非在所有情况下都能做到。如果 webpack 无法合并模块,则有两种替代方案:Prevent 和 Root。Prevent 意味着模块必须在自己的作用域中。Root 意味着将创建新的模块组。以下条件决定结果

条件结果
非 ES6 模块阻止
由非导入导入
从其他 Chunk 导入
由多个其他模块组导入
使用 import() 导入
ProvidePlugin 或使用 module 影响阻止
HMR 接受
使用 eval()阻止
在多个 Chunk 中阻止
export * from "cjs-module"阻止

模块分组算法

以下伪 JavaScript 解释了该算法

modules.forEach((module) => {
  const group = new ModuleGroup({
    root: module,
  });
  module.dependencies.forEach((dependency) => {
    tryToAdd(group, dependency);
  });
  if (group.modules.length > 1) {
    orderedModules = topologicalSort(group.modules);
    concatenatedModule = new ConcatenatedModule(orderedModules);
    chunk.add(concatenatedModule);
    orderedModules.forEach((groupModule) => {
      chunk.remove(groupModule);
    });
  }
});

function tryToAdd(group, module) {
  if (group.has(module)) {
    return true;
  }
  if (!hasPreconditions(module)) {
    return false;
  }
  const nextGroup = group;
  const result = module.dependents.reduce((check, dependent) => {
    return check && tryToAdd(nextGroup, dependent);
  }, true);
  if (!result) {
    return false;
  }
  module.dependencies.forEach((dependency) => {
    tryToAdd(group, dependency);
  });
  group.merge(nextGroup);
  return true;
}

调试优化跳过

使用 webpack CLI 时,--stats-optimization-bailout 标志将显示跳过原因。使用 webpack 配置时,将以下内容添加到 stats 对象

module.exports = {
  //...
  stats: {
    // Display bailout reasons
    optimizationBailout: true,
  },
};

插件

Webpack 拥有丰富的插件接口。webpack 内部的大多数功能都使用此插件接口。这使得 webpack 灵活

名称描述
BannerPlugin在每个生成的 chunk 顶部添加一个 banner
ChunksWebpackPlugin创建包含入口点和 chunk 关系以服务您的 bundle 的 HTML 文件
CommonsChunkPlugin提取 chunk 之间共享的公共模块
CompressionWebpackPlugin准备压缩版的资产以 Content-Encoding 方式提供
ContextReplacementPlugin覆盖 require 表达式的推断上下文
CopyWebpackPlugin将单个文件或整个目录复制到构建目录
DefinePlugin允许在编译时配置全局常量
DllPlugin拆分 bundle 以大幅缩短构建时间
EnvironmentPlugin使用 DefinePlugin 处理 process.env 键的简写
EslintWebpackPlugin一个用于 webpack 的 ESLint 插件
HotModuleReplacementPlugin启用热模块替换 (HMR)
HtmlWebpackPlugin轻松创建 HTML 文件以服务您的 bundle
IgnorePlugin从 bundle 中排除某些模块
LimitChunkCountPlugin设置 chunk 的最小/最大限制以更好地控制 chunk
MinChunkSizePlugin保持 chunk 大小超过指定限制
MiniCssExtractPlugin为每个需要 CSS 的 JS 文件创建一个 CSS 文件
NoEmitOnErrorsPlugin当存在编译错误时跳过发出阶段
NormalModuleReplacementPlugin替换匹配正则表达式的资源
NpmInstallWebpackPlugin在开发过程中自动安装缺失的依赖项
ProgressPlugin报告编译进度
ProvidePlugin无需使用 import/require 即可使用模块
SourceMapDevToolPlugin实现对源映射更细粒度的控制
EvalSourceMapDevToolPlugin实现对 eval 源映射更细粒度的控制
SvgChunkWebpackPlugin根据您的入口点依赖项生成经过 SVGO 优化的 SVG 精灵图
TerserPlugin使用 Terser 压缩项目中的 JS

更多第三方插件,请参阅 awesome-webpack 列表。

ModuleFederationPlugin

ModuleFederationPlugin 允许在运行时构建提供或消费与其他独立构建的模块。

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // options' typings in typescript
      runtime: string | false,
    }),
  ],
};

选项

runtime

创建具有指定名称的新运行时 chunk。

webpack.config.js

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      runtime: 'my-runtime-name',
    }),
  ],
};

共享库

通过配置中的 shared 键,您可以定义在您的联邦模块之间共享的库。包名与您的 package.json 的 dependencies 部分中的包名相同。但是,默认情况下,webpack 只会共享库的根级别。

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // adds date-fns as shared module
      shared: ['date-fns'],
    }),
  ],
};

因此在您的应用程序中,您可以执行类似以下操作

import { format } from 'date-fns';

format(new Date(2014, 1, 11), 'MM/dd/yyyy');

webpack 将自动在所有将 date-fns 定义为共享库的联邦模块之间共享 date-fns。但是,如果您想访问不在包根级别的内容,例如 date-fns/locale/en-GB/index.js,您需要在 shared 配置中将 / 附加到包名中

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // adds date-fns as shared module
      // all files of the package will be shared
      shared: ['date-fns/'],
    }),
  ],
};

/ 语法允许您访问包的所有文件。但是,它应仅在必要时使用,因为它会对性能产生影响,尤其是在 development 模式下。

指定包版本

有三种方式指定共享库的版本。

数组语法

此语法允许您仅通过包名共享库。这种方法适用于原型设计,但鉴于 reactreact-dom 等库将需要额外的要求,它不允许您扩展到大型生产环境。

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // adds lodash as shared module
      // version is inferred from package.json
      // there is no version check for the required version
      // so it will always use the higher version found
      shared: ['lodash'],
    }),
  ],
};
对象语法

此语法为您提供了对每个共享库的更多控制,您可以在其中将包名定义为键,将版本 (semver) 定义为值。

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      shared: {
        // adds lodash as shared module
        // version is inferred from package.json
        // it will use the highest lodash version that is >= 4.17 and < 5
        lodash: '^4.17.0',
      },
    }),
  ],
};
带共享提示的对象语法

此语法允许您向每个共享包提供额外的 提示,其中您将包名定义为键,并将值定义为包含用于修改共享行为的提示的对象。

const deps = require('./package.json').dependencies;

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      shared: {
        // adds react as shared module
        react: {
          requiredVersion: deps.react,
          singleton: true,
        },
      },
    }),
  ],
};

共享提示

eager

布尔值

此提示将允许 webpack 直接包含提供的模块和回退模块,而不是通过异步请求获取库。换句话说,这允许在初始 chunk 中使用此共享模块。此外,请注意,当启用此提示时,所有提供的模块和回退模块将始终被下载。

import

false | 字符串

应放置在共享作用域中的提供的模块。如果共享作用域中找不到共享模块或版本无效,此提供的模块也作为回退模块。(此提示的值默认为属性名。)

packageName

string

用于从描述文件确定所需版本的包名。仅当无法从请求自动确定包名时才需要此项。

requiredVersion

false string

此字段指定包的所需版本。它接受语义版本控制,例如 "^1.2.3"。此外,如果以 URL 形式提供版本,它也会检索,例如:"git+ssh://git@github.com:foo/bar.git#v1.0.0"。

shareKey

string

请求的共享模块将从共享作用域中以此键查找。

shareScope

string

共享作用域的名称。

singleton

布尔值

此提示仅允许共享作用域中存在单个版本的共享模块(默认禁用)。有些库使用全局内部状态(例如 react, react-dom)。因此,同时只运行一个库实例至关重要。

如果共享作用域中存在同一依赖项的多个版本,则使用最高语义版本。

strictVersion

布尔值

此提示允许 webpack 在版本无效时拒绝共享模块(当本地回退模块可用且共享模块不是单例时默认为 true,否则为 false;如果未指定所需版本,则无效)。如果未找到所需版本,则抛出运行时错误。

version

false | 字符串

提供的模块的版本。它允许 webpack 替换较低匹配的版本,但不能替换更高版本。

默认情况下,webpack 使用依赖项 package.json 文件中的版本。

其他示例

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // adds vue as shared module
      // version is inferred from package.json
      // it will always use the shared version, but print a warning when the shared vue is < 2.6.5 or >= 3
      shared: {
        vue: {
          requiredVersion: '^2.6.5',
          singleton: true,
        },
      },
    }),
  ],
};
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // adds vue as shared module
      // there is no local version provided
      // it will emit a warning if the shared vue is < 2.6.5 or >= 3
      shared: {
        vue: {
          import: false,
          requiredVersion: '^2.6.5',
        },
      },
    }),
  ],
};
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // adds vue as shared module
      // there is no local version provided
      // it will throw an error when the shared vue is < 2.6.5 or >= 3
      shared: {
        vue: {
          import: false,
          requiredVersion: '^2.6.5',
          strictVersion: true,
        },
      },
    }),
  ],
};
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      shared: {
        'my-vue': {
          // can be referenced by import "my-vue"
          import: 'vue', // the "vue" package will be used as a provided and fallback module
          shareKey: 'shared-vue', // under this name the shared module will be placed in the share scope
          shareScope: 'default', // share scope with this name will be used
          singleton: true, // only a single version of the shared module is allowed
          strictVersion: true, // don't use shared version when version isn't valid. Singleton or modules without fallback will throw, otherwise fallback is used
          version: '1.2.3', // the version of the shared module
          requiredVersion: '^1.0.0', // the required version of the shared module
        },
      },
    }),
  ],
};

NoEmitOnErrorsPlugin

NoEmitOnErrorsPlugin 允许您在出现任何错误时避免发出资产。默认启用,您可以使用 optimization.emitOnErrors 禁用它

webpack.config.js

module.exports = {
  plugins: [new webpack.NoEmitOnErrorsPlugin()],
};

NormalModuleReplacementPlugin

NormalModuleReplacementPlugin 允许您用 newResource 替换与 resourceRegExp 匹配的资源。如果 newResource 是相对路径,则它相对于先前的资源进行解析。如果 newResource 是一个函数,则预期它会覆盖所提供资源的请求属性。

这对于允许在不同构建之间实现不同行为非常有用。

new webpack.NormalModuleReplacementPlugin(resourceRegExp, newResource);

请注意,resourceRegExp 是针对您在代码中编写的请求进行测试的,而不是解析后的资源。例如,当您的代码为 import sum from './sum' 时,将使用 './sum' 进行测试,而不是 './sum.js'

另请注意,在使用 Windows 时,您必须适应不同的文件夹分隔符。例如,/src\/environments\/environment\.ts/ 在 Windows 上无法工作,您必须使用 /src[\\/]environments[\\/]environment\.ts/, 代替。

基本示例

在为 开发环境 构建时替换特定模块。

假设您有一个配置文件 some/path/config.development.module.js,以及一个用于生产的特殊版本 some/path/config.production.module.js

在为生产环境构建时添加以下插件

new webpack.NormalModuleReplacementPlugin(
  /some\/path\/config\.development\.js/,
  './config.production.js'
);

高级示例

根据 指定环境 进行条件构建。

假设您希望为不同的构建目标配置具有特定值的配置。

module.exports = function (env) {
  var appTarget = env.APP_TARGET || 'VERSION_A';
  return {
    plugins: [
      new webpack.NormalModuleReplacementPlugin(/-APP_TARGET$/, function (
        resource
      ) {
        resource.request = resource.request.replace(
          /-APP_TARGET/,
          `-${appTarget}`
        );

        if (resource.createData) {
          resource.createData.request = resource.request;
        }
      }),
    ],
  };
};

创建两个配置文件

app/config-VERSION_A.js

export default {
  title: 'I am version A',
};

app/config-VERSION_B.js

export default {
  title: 'I am version B',
};

然后使用您在正则表达式中查找的关键字导入该配置

import config from 'app/config-APP_TARGET';
console.log(config.title);

现在,根据您要构建的目标,您将导入正确的配置

npx webpack --env APP_TARGET=VERSION_A
=> 'I am version A'

npx webpack --env APP_TARGET=VERSION_B
=> 'I am version B'

PrefetchPlugin

预取常规模块请求,使其在首次 importrequire 该模块之前得到解析和构建。使用此插件可以提高性能。请先分析构建,以确定明智的预取点。

new webpack.PrefetchPlugin([context], request);

选项

  • context:目录的绝对路径
  • request:常规模块的请求字符串

ProfilingPlugin

生成包含插件执行时间的 Chrome 性能分析文件。默认输出 events.json 文件。可以通过 outputPath 选项提供自定义文件路径。

注意:ProfilingPlugin 只接受绝对路径。

选项

  • outputPath:自定义输出文件(json)的绝对路径

用法:默认

new webpack.debug.ProfilingPlugin();

用法:自定义 outputPath

new webpack.debug.ProfilingPlugin({
  outputPath: path.join(__dirname, 'profiling/profileEvents.json'),
});

要查看性能分析文件

  1. 使用 ProfilingPlugin 运行 webpack。
  2. 转到 Chrome,打开 DevTools,然后转到 Performance 选项卡(以前是 Timeline)。
  3. 将生成的文件(默认是 events.json)拖放到性能分析器中。

然后它将显示时间轴统计和每个插件的调用!

ProgressPlugin

ProgressPlugin 提供了一种自定义编译期间报告进度的方式。

用法

创建一个 ProgressPlugin 实例并提供允许的参数之一,此外,还有一个静态方法 createDefaultHandler 可用于自定义默认处理程序。

提供 function

提供一个处理函数,该函数将在钩子报告进度时被调用。handler 函数参数

  • percentage:一个介于 0 和 1 之间的数字,表示编译完成的百分比
  • message:当前正在执行的钩子的简短描述
  • ...args:零个或多个附加字符串,描述当前进度
const handler = (percentage, message, ...args) => {
  // e.g. Output each progress message directly to the console:
  console.info(percentage, message, ...args);
};

new webpack.ProgressPlugin(handler);

提供 object

ProgressPlugin 提供 object 时,支持以下属性

  • activeModules (boolean = false):在进度消息中显示活动模块数量和一个活动模块。
  • entries (boolean = true):在进度消息中显示入口数量。
  • handler(参见 提供函数
  • modules (boolean = true):在进度消息中显示模块数量。
  • modulesCount (number = 5000):开始的最小模块数量。当 modules 属性启用时生效。
  • profile (boolean = false):告诉 ProgressPlugin 收集进度步骤的分析数据。
  • dependencies (boolean = true):在进度消息中显示依赖项数量。
  • dependenciesCount (number = 10000):开始的最小依赖项数量。当 dependencies 属性启用时生效。
  • percentBy (string = null: 'entries' | 'dependencies' | 'modules' | null):告诉 ProgressPlugin 如何计算进度百分比。
new webpack.ProgressPlugin({
  activeModules: false,
  entries: true,
  handler(percentage, message, ...args) {
    // custom logic
  },
  modules: true,
  modulesCount: 5000,
  profile: false,
  dependencies: true,
  dependenciesCount: 10000,
  percentBy: null,
});

webpack.ProgressPlugin.createDefaultHandler

如果 ProgressPlugin 的默认处理程序不满足您的要求,您可以使用静态方法 ProgressPlugin.createDefaultHandler 进行自定义。

static createDefaultHandler: (
  profile: undefined | null | boolean,
  logger: WebpackLogger
) => (percentage: number, msg: string, ...args: string[]) => void;

百分比计算

默认情况下,进度百分比是根据已构建模块数量和总模块数量计算的:built / total

总模块数量是未知的,并在构建过程中发生变化。这可能导致不准确的进度百分比。

为了解决这个问题,ProgressPlugin 缓存了最后已知的总模块数量,并在下一次构建时重用此值。第一次构建将预热缓存,但随后的构建将使用并更新此值。

对于具有 多个配置入口点 的项目,我们建议使用 percentBy: 'entries' 设置。百分比计算将变得更准确,因为入口点的数量是预先知道的。

支持的钩子

以下钩子向 ProgressPlugin 报告进度信息。

编译器

  • compilation
  • emit*
  • afterEmit*
  • done

编译

  • buildModule
  • failedModule
  • succeedModule
  • finishModules*
  • seal*
  • optimizeDependenciesBasic*
  • optimizeDependencies*
  • optimizeDependenciesAdvanced*
  • afterOptimizeDependencies*
  • optimize*
  • optimizeModulesBasic*
  • optimizeModules*
  • optimizeModulesAdvanced*
  • afterOptimizeModules*
  • optimizeChunksBasic*
  • optimizeChunks*
  • optimizeChunksAdvanced*
  • afterOptimizeChunks*
  • optimizeTree*
  • afterOptimizeTree*
  • optimizeChunkModulesBasic*
  • optimizeChunkModules*
  • optimizeChunkModulesAdvanced*
  • afterOptimizeChunkModules*
  • reviveModules*
  • optimizeModuleOrder*
  • advancedOptimizeModuleOrder*
  • beforeModuleIds*
  • moduleIds*
  • optimizeModuleIds*
  • afterOptimizeModuleIds*
  • reviveChunks*
  • optimizeChunkOrder*
  • beforeChunkIds*
  • optimizeChunkIds*
  • afterOptimizeChunkIds*
  • recordModules*
  • recordChunks*
  • beforeHash*
  • afterHash*
  • recordHash*
  • beforeModuleAssets*
  • beforeChunkAssets*
  • additionalChunkAssets*
  • record*
  • additionalAssets*
  • optimizeChunkAssets*
  • afterOptimizeChunkAssets*
  • optimizeAssets*
  • afterOptimizeAssets*
  • afterSeal*

来源

ProvidePlugin

自动加载模块,无需在每个地方都 importrequire 它们。

new webpack.ProvidePlugin({
  identifier: 'module1',
  // ...
});

new webpack.ProvidePlugin({
  identifier: ['module1', 'property1'],
  // ...
});

默认情况下,模块解析路径是当前文件夹 (./**)node_modules)。

也可以指定完整路径

const path = require('path');

new webpack.ProvidePlugin({
  identifier: path.resolve(path.join(__dirname, 'src/module1')),
  // ...
});

每当在模块中遇到 identifier 作为自由变量时,module 将自动加载,并且 identifier 将填充已加载 module 的导出(或 property 以支持命名导出)。

要导入 ES2015 模块的默认导出,您必须指定模块的默认属性。

用法:jQuery

要自动加载 jquery,我们可以将它公开的两个变量指向相应的 node 模块

new webpack.ProvidePlugin({
  $: 'jquery',
  jQuery: 'jquery',
});

然后在我们的任何源代码中

// in a module
$('#item'); // <= works
jQuery('#item'); // <= also works
// $ is automatically set to the exports of module "jquery"

用法:jQuery 与 Angular 1

Angular 会查找 window.jQuery 来确定 jQuery 是否存在,请参阅 源代码

new webpack.ProvidePlugin({
  'window.jQuery': 'jquery',
});

用法:Lodash Map

new webpack.ProvidePlugin({
  _map: ['lodash', 'map'],
});

用法:Vue.js

new webpack.ProvidePlugin({
  Vue: ['vue/dist/vue.esm.js', 'default'],
});

SourceMapDevToolPlugin

此插件可以更精细地控制源映射生成。它也会在 devtool 配置选项的某些设置下自动启用。

new webpack.SourceMapDevToolPlugin(options);

选项

支持以下选项

  • test (string RegExp [string, RegExp]):根据模块的扩展名包含源映射(默认为 .js.mjs.css)。

  • include (string RegExp [string, RegExp]):包含与给定值匹配的模块路径的源映射。

  • exclude (string RegExp [string, RegExp]):从源映射生成中排除与给定值匹配的模块。

  • filename (string):定义 SourceMap 的输出文件名(如果未提供值,则内联)。

  • append (string function false):将给定值附加到原始资产。通常是 #sourceMappingURL 注释。[url] 将替换为指向源映射文件的 URL。自 webpack v4.36.0 起,支持路径参数:[chunk][filename][contenthash]。将 append 设置为 false 将禁用附加。

    从版本 5.84.0 开始,webpack 允许 append 选项是一个函数,该函数接受路径数据和资产信息对象作为参数,并返回一个字符串。

    (pathData: PathData, assetInfo?: AssetInfo) => string;
  • moduleFilenameTemplate (string):请参阅 output.devtoolModuleFilenameTemplate

  • fallbackModuleFilenameTemplate (string):参见上方链接。

  • namespace (string):参见 output.devtoolNamespace

  • module = true (boolean):指示加载器是否应生成源映射。

  • columns = true (boolean):指示是否应使用列映射。

  • noSources = false (boolean):阻止源文件内容包含在源映射中。

  • publicPath (string):发出带有公共路径前缀的绝对 URL,例如 https://example.com/project/

  • fileContext (string):使 [file] 参数相对于此目录。

  • sourceRoot (string):为 SourceMap 中的 sourceRoot 属性提供自定义值。

  • debugIds (boolean):如果为 true,则会在源和源映射中发出唯一 ID,从而简化跨不同构建识别源映射。有关更多详细信息,请参见 TC39 源映射调试 ID 提案

当您希望将源映射存储在上层目录以避免在绝对 [url] 中出现 ../../ 时,fileContext 选项很有用。

示例

以下示例展示了此插件的一些常见用例。

基本用例

您可以使用以下代码将配置选项 devtool: inline-source-map 替换为等效的自定义插件配置

module.exports = {
  // ...
  devtool: false,
  plugins: [new webpack.SourceMapDevToolPlugin({})],
};

排除供应商映射

以下代码将排除 vendor.js 包中任何模块的源映射

new webpack.SourceMapDevToolPlugin({
  filename: '[file].map[query]',
  exclude: ['vendor.js'],
});

外部托管源映射

设置源映射的 URL。对于需要在授权的主机上托管它们非常有用。

new webpack.SourceMapDevToolPlugin({
  append: '\n//# sourceMappingURL=https://example.com/sourcemap/[url]',
  filename: '[file].map[query]',
});

对于源映射存储在上层目录的情况

project
|- dist
  |- public
    |- bundle-[hash].js
  |- sourcemaps
    |- bundle-[hash].js.map

使用以下配置

new webpack.SourceMapDevToolPlugin({
  filename: 'sourcemaps/[file].map',
  publicPath: 'https://example.com/project/',
  fileContext: 'public',
});

将生成以下 URL

https://example.com/project/sourcemaps/bundle-[hash].js.map

SplitChunksPlugin

最初,chunk(以及其中导入的模块)通过 webpack 内部图中的父子关系连接。CommonsChunkPlugin 用于避免它们之间重复的依赖项,但无法进行进一步优化。

自 webpack v4 起,CommonsChunkPlugin 被移除,转而支持 optimization.splitChunks

默认值

开箱即用的 SplitChunksPlugin 对大多数用户来说应该工作良好。

默认情况下,它只影响按需加载的 chunk,因为更改初始 chunk 会影响 HTML 文件应该包含的脚本标签以运行项目。

Webpack 将根据以下条件自动拆分 chunk

  • 新 chunk 可以共享 或者 模块来自 node_modules 文件夹
  • 新 chunk 将大于 20kb(压缩和 gzip 前)
  • 按需加载 chunk 时的最大并行请求数小于或等于 30
  • 初始页面加载时的最大并行请求数小于或等于 30

在尝试满足最后两个条件时,优先选择更大的 chunk。

配置

Webpack 为希望更好地控制此功能的开发人员提供了一组选项。

optimization.splitChunks

此配置对象表示 SplitChunksPlugin 的默认行为。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks: 'async',
      minSize: 20000,
      minRemainingSize: 0,
      minChunks: 1,
      maxAsyncRequests: 30,
      maxInitialRequests: 30,
      enforceSizeThreshold: 50000,
      cacheGroups: {
        defaultVendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
          reuseExistingChunk: true,
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true,
        },
      },
    },
  },
};

splitChunks.automaticNameDelimiter

string = '~'

默认情况下,webpack 将使用 chunk 的来源和名称生成名称(例如 vendors~main.js)。此选项允许您指定用于生成名称的分隔符。

splitChunks.chunks

string = 'async' function (chunk) RegExp

这指示将选择哪些 chunk 进行优化。当提供字符串时,有效值为 allasyncinitial。提供 all 可能特别强大,因为它意味着 chunk 甚至可以在异步和非异步 chunk 之间共享。

请注意,它也适用于回退缓存组(splitChunks.fallbackCacheGroup.chunks)。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      // include all types of chunks
      chunks: 'all',
    },
  },
};

或者,您可以提供一个函数以进行更多控制。返回值将指示是否包含每个 chunk。

module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks(chunk) {
        // exclude `my-excluded-chunk`
        return chunk.name !== 'my-excluded-chunk';
      },
    },
  },
};

如果您使用 webpack 5.86.0 或更高版本,您还可以传递正则表达式

module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks: /foo/,
    },
  },
};

splitChunks.maxAsyncRequests

number = 30

按需加载时的最大并行请求数。

splitChunks.maxInitialRequests

number = 30

入口点的最大并行请求数。

splitChunks.defaultSizeTypes

[string] = ['javascript', 'unknown']

设置当使用数字表示大小时所使用的大小类型。

splitChunks.minChunks

number = 1

模块在拆分之前在 chunk 之间共享的最小次数。

splitChunks.hidePathInfo

布尔值

创建按 maxSize 拆分的部分的名称时,防止暴露路径信息。

splitChunks.minSize

number = 20000 { [index: string]: number }

生成 chunk 的最小大小(以字节为单位)。

splitChunks.minSizeReduction

number { [index: string]: number }

生成 chunk 所需的主 chunk (bundle) 的最小大小减小量(以字节为单位)。这意味着如果拆分成一个 chunk 没有将主 chunk (bundle) 的大小减少给定数量的字节,即使它满足 splitChunks.minSize 值,它也不会被拆分。

splitChunks.enforceSizeThreshold

splitChunks.cacheGroups.{cacheGroup}.enforceSizeThreshold

number = 50000

强制执行拆分且忽略其他限制(minRemainingSize、maxAsyncRequests、maxInitialRequests)的大小阈值。

splitChunks.minRemainingSize

splitChunks.cacheGroups.{cacheGroup}.minRemainingSize

number = 0

splitChunks.minRemainingSize 选项在 webpack 5 中引入,通过确保拆分后剩余的 chunk 的最小大小超过限制来避免零大小模块。在 'development' 模式 中默认为 0。对于其他情况,splitChunks.minRemainingSize 默认为 splitChunks.minSize 的值,因此除了需要深度控制的极少数情况外,无需手动指定。

splitChunks.layer

splitChunks.cacheGroups.{cacheGroup}.layer

RegExp string function

按模块层将模块分配到缓存组。

splitChunks.maxSize

number = 0

使用 maxSize(无论是全局的 optimization.splitChunks.maxSize,还是每个缓存组的 optimization.splitChunks.cacheGroups[x].maxSize,或回退缓存组的 optimization.splitChunks.fallbackCacheGroup.maxSize)会告诉 webpack 尝试将大于 maxSize 字节的 chunk 拆分成更小的部分。这些部分的最小大小将为 minSize(靠近 maxSize)。该算法是确定性的,模块的更改只会产生局部影响。因此,它在使用长期缓存时可用,并且不需要记录。maxSize 只是一个提示,当模块大于 maxSize 或拆分会违反 minSize 时可能会被违反。

当 chunk 已经有名称时,每个部分将获得一个从该名称派生出来的新名称。根据 optimization.splitChunks.hidePathInfo 的值,它将添加一个从第一个模块名称派生出来的键或其哈希值。

maxSize 选项旨在与 HTTP/2 和长期缓存一起使用。它增加了请求数量以实现更好的缓存。它也可以用于减小文件大小以加快重建速度。

splitChunks.maxAsyncSize

数字

maxSize 类似,maxAsyncSize 可以全局应用(splitChunks.maxAsyncSize),应用于缓存组(splitChunks.cacheGroups.{cacheGroup}.maxAsyncSize),或应用于回退缓存组(splitChunks.fallbackCacheGroup.maxAsyncSize)。

maxAsyncSizemaxSize 之间的区别在于 maxAsyncSize 只会影响按需加载的 chunk。

splitChunks.maxInitialSize

数字

maxSize 类似,maxInitialSize 可以全局应用(splitChunks.maxInitialSize),应用于缓存组(splitChunks.cacheGroups.{cacheGroup}.maxInitialSize),或应用于回退缓存组(splitChunks.fallbackCacheGroup.maxInitialSize)。

maxInitialSizemaxSize 之间的区别在于 maxInitialSize 只会影响初始加载的 chunk。

splitChunks.name

boolean = false function (module, chunks, cacheGroupKey) => string string

也可用于每个缓存组:splitChunks.cacheGroups.{cacheGroup}.name

拆分 chunk 的名称。提供 false 将保持 chunk 的相同名称,因此它不会不必要地更改名称。这是生产构建的推荐值。

提供字符串或函数允许您使用自定义名称。指定字符串或始终返回相同字符串的函数将把所有公共模块和供应商合并到一个 chunk 中。这可能导致初始下载量更大并减慢页面加载速度。

如果您选择指定函数,您可能会发现 chunk.name 属性(其中 chunkchunks 数组的一个元素)在为您的 chunk 选择名称时特别有用。

如果 splitChunks.name入口点 名称匹配,则入口点 chunk 和缓存组将合并到一个 chunk 中。

main.js

import _ from 'lodash';

console.log(_.join(['Hello', 'webpack'], ' '));

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        commons: {
          test: /[\\/]node_modules[\\/]/,
          // cacheGroupKey here is `commons` as the key of the cacheGroup
          name(module, chunks, cacheGroupKey) {
            const moduleFileName = module
              .identifier()
              .split('/')
              .reduceRight((item) => item);
            const allChunksNames = chunks.map((item) => item.name).join('~');
            return `${cacheGroupKey}-${allChunksNames}-${moduleFileName}`;
          },
          chunks: 'all',
        },
      },
    },
  },
};

运行 webpack 并使用以下 splitChunks 配置还将输出一个通用组的 chunk,名称为:commons-main-lodash.js.e7519d2bb8777058fa27.js(哈希作为真实世界输出的示例)。

splitChunks.usedExports

splitChunks.cacheGroups{cacheGroup}.usedExports

boolean = true

找出模块使用了哪些导出,以便混淆导出名称,省略未使用的导出并生成更高效的代码。当它为 true 时:分析每个运行时的已使用导出,当它为 "global" 时:全局分析所有运行时组合的导出)。

splitChunks.cacheGroups

缓存组可以继承和/或覆盖 splitChunks.* 中的任何选项;但 testpriorityreuseExistingChunk 只能在缓存组级别配置。要禁用任何默认缓存组,请将其设置为 false

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        default: false,
      },
    },
  },
};

splitChunks.cacheGroups.{cacheGroup}.priority

number = -20

一个模块可以属于多个缓存组。优化将优先选择具有更高 priority 的缓存组。默认组具有负优先级,以允许自定义组具有更高优先级(自定义组的默认值为 0)。

splitChunks.cacheGroups.{cacheGroup}.reuseExistingChunk

boolean = true

如果当前 chunk 包含已经从主 bundle 中拆分出来的模块,则会重用它,而不是生成新的 chunk。这可能会影响 chunk 的最终文件名。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        defaultVendors: {
          reuseExistingChunk: true,
        },
      },
    },
  },
};

splitChunks.cacheGroups.{cacheGroup}.type

function RegExp string

允许按模块类型将模块分配到缓存组。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        json: {
          type: 'json',
        },
      },
    },
  },
};

splitChunks.cacheGroups.test

splitChunks.cacheGroups.{cacheGroup}.test

function (module, { chunkGraph, moduleGraph }) => boolean RegExp string

控制此缓存组选择哪些模块。省略它将选择所有模块。它可以匹配绝对模块资源路径或 chunk 名称。当匹配 chunk 名称时,将选择该 chunk 中的所有模块。

{cacheGroup}.test 提供函数

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        svgGroup: {
          test(module) {
            // `module.resource` contains the absolute path of the file on disk.
            // Note the usage of `path.sep` instead of / or \, for cross-platform compatibility.
            const path = require('path');
            return (
              module.resource &&
              module.resource.endsWith('.svg') &&
              module.resource.includes(`${path.sep}cacheable_svgs${path.sep}`)
            );
          },
        },
        byModuleTypeGroup: {
          test(module) {
            return module.type === 'javascript/auto';
          },
        },
      },
    },
  },
};

要查看 modulechunks 对象中可用的信息,您可以在回调中放置 debugger; 语句。然后 在调试模式下运行您的 webpack 构建 以在 Chromium DevTools 中检查参数。

{cacheGroup}.test 提供 RegExp

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        defaultVendors: {
          // Note the usage of `[\\/]` as a path separator for cross-platform compatibility.
          test: /[\\/]node_modules[\\/]|vendor[\\/]analytics_provider|vendor[\\/]other_lib/,
        },
      },
    },
  },
};

splitChunks.cacheGroups.{cacheGroup}.filename

string function (pathData, assetInfo) => string

仅当它是初始 chunk 时才允许覆盖文件名。output.filename 中可用的所有占位符在此处也可用。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        defaultVendors: {
          filename: '[name].bundle.js',
        },
      },
    },
  },
};

并作为函数

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        defaultVendors: {
          filename: (pathData) => {
            // Use pathData object for generating filename string based on your requirements
            return `${pathData.chunk.name}-bundle.js`;
          },
        },
      },
    },
  },
};

可以通过提供文件名路径前缀来创建文件夹结构:'js/vendor/bundle.js'

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        defaultVendors: {
          filename: 'js/[name]/bundle.js',
        },
      },
    },
  },
};

splitChunks.cacheGroups.{cacheGroup}.enforce

boolean = false

告诉 webpack 忽略 splitChunks.minSizesplitChunks.minChunkssplitChunks.maxAsyncRequestssplitChunks.maxInitialRequests 选项,并始终为此缓存组创建 chunk。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        defaultVendors: {
          enforce: true,
        },
      },
    },
  },
};

splitChunks.cacheGroups.{cacheGroup}.idHint

string

设置 chunk ID 的提示。它将被添加到 chunk 的文件名中。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        defaultVendors: {
          idHint: 'vendors',
        },
      },
    },
  },
};

示例

默认值:示例 1

// index.js

import('./a'); // dynamic import
// a.js
import 'react';

//...

结果:将创建一个包含 react 的单独 chunk。在导入调用时,此 chunk 与包含 ./a 的原始 chunk 并行加载。

为什么?

  • 条件 1:chunk 包含来自 node_modules 的模块
  • 条件 2:react 大于 30kb
  • 条件 3:导入调用时的并行请求数为 2
  • 条件 4:不影响初始页面加载时的请求

这背后的理由是什么?react 可能不会像您的应用程序代码那样频繁更改。通过将其移动到单独的 chunk 中,此 chunk 可以与您的应用程序代码分开缓存(假设您正在使用 chunkhash、records、Cache-Control 或其他长期缓存方法)。

默认值:示例 2

// entry.js

// dynamic imports
import('./a');
import('./b');
// a.js
import './helpers'; // helpers is 40kb in size

//...
// b.js
import './helpers';
import './more-helpers'; // more-helpers is also 40kb in size

//...

结果:将创建一个包含 ./helpers 及其所有依赖项的单独 chunk。在导入调用时,此 chunk 与原始 chunk 并行加载。

为什么?

  • 条件 1:chunk 在两个导入调用之间共享
  • 条件 2:helpers 大于 30kb
  • 条件 3:导入调用时的并行请求数为 2
  • 条件 4:不影响初始页面加载时的请求

helpers 的内容放入每个 chunk 将导致其代码被下载两次。通过使用单独的 chunk,这只会发生一次。我们付出了额外请求的代价,这可以被视为一种权衡。这就是为什么有 30kb 的最小大小。

拆分 Chunk:示例 1

创建一个 commons chunk,其中包含入口点之间共享的所有代码。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        commons: {
          name: 'commons',
          chunks: 'initial',
          minChunks: 2,
        },
      },
    },
  },
};

拆分 Chunk:示例 2

创建一个 vendors chunk,其中包含整个应用程序中来自 node_modules 的所有代码。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        commons: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
      },
    },
  },
};

拆分 Chunk:示例 3

创建一个 custom vendor chunk,其中包含由 RegExp 匹配的特定 node_modules 包。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
          name: 'vendor',
          chunks: 'all',
        },
      },
    },
  },
};

StylelintWebpackPlugin

npm node tests coverage discussion size

此版本的 stylelint-webpack-plugin 仅适用于 webpack 5。对于 webpack 4,请参阅 2.x 分支

此插件使用 stylelint,它可以帮助您避免错误并强制执行样式约定。

入门

首先,您需要安装 stylelint-webpack-plugin

npm install stylelint-webpack-plugin --save-dev

yarn add -D stylelint-webpack-plugin

pnpm add -D stylelint-webpack-plugin

[!注意]

如果您尚未安装,还需要从 npm 安装 stylelint >= 13

npm install stylelint --save-dev

yarn add -D stylelint

pnpm add -D stylelint

[!注意]

如果您使用的是 Stylelint 13 而不是 14+,如果您遇到 Stylelint 相关的类型错误,您可能还需要安装 @types/stylelint 作为开发依赖。

然后将插件添加到您的 webpack 配置中。例如

const StylelintPlugin = require('stylelint-webpack-plugin');

module.exports = {
  // ...
  plugins: [new StylelintPlugin(options)],
  // ...
};

选项

有关可用选项的完整列表,请参见 stylelint 的选项。这些选项直接传递给 stylelint

cache

  • 类型
type cache = boolean;
  • 默认值:true

缓存默认启用以减少执行时间。

cacheLocation

  • 类型
type cacheLocation = string;
  • 默认值:node_modules/.cache/stylelint-webpack-plugin/.stylelintcache

指定缓存位置的路径。这可以是文件或目录。

configFile

  • 类型
type context = string;
  • 默认值:undefined

指定 stylelint 将使用的配置文件位置。

注意

默认情况下,这由 stylelint 处理

context

  • 类型
type context = string;
  • 默认值:compiler.context

一个字符串,指示您的文件根目录。

exclude

  • 类型
type exclude = string | Array<string>;
  • 默认值:['node_modules', compiler.options.output.path]

指定要排除的文件和/或目录。必须相对于 options.context

extensions

  • 类型
type extensions = string | Array<string>;
  • 默认值:['css', 'scss', 'sass']

指定应检查的扩展名。

files

  • 类型
type files = string | Array<string>;
  • 默认值:null

指定目录、文件或 glob 模式。必须相对于 options.context。目录将被递归遍历,查找与 options.extensions 匹配的文件。文件和 glob 模式将忽略 options.extensions

fix

  • 类型
type fix = boolean;
  • 默认值:false

如果为 truestylelint 将尽可能多地修复错误。修复会直接应用于源文件。所有未修复的错误都将报告。请参阅 自动修复错误 文档。

formatter

  • 类型
type formatter = string | (
  results: Array<import('stylelint').LintResult>
) => string
  • 默认值: 'string'

指定您希望用于格式化结果的格式化程序。请参阅格式化程序选项

lintDirtyModulesOnly

  • 类型
type lintDirtyModulesOnly = boolean;
  • 默认值:false

仅对更改的文件进行 Lint;启动时跳过 Lint。

stylelintPath

  • 类型
type stylelintPath = string;
  • 默认值: stylelint

将用于 Lint 的 stylelint 实例的路径。

threads

  • 类型
type threads = boolean | number;
  • 默认值:false

设置为 true 可根据 CPU 数量自动选择池大小。设置为大于 1 的数字可设置明确的池大小。

设置为 false、1 或更小可禁用并在主进程中运行。

错误和警告

默认情况下,插件将根据 Stylelint 错误/警告的数量自动调整错误报告。

您仍然可以通过使用 emitError emitWarning 选项来强制执行此行为

emitError

  • 类型
type emitError = boolean;
  • 默认值:true

找到的错误将始终被发出。要禁用,请设置为 false

emitWarning

  • 类型
type emitWarning = boolean;
  • 默认值:true

找到的警告将始终被发出。要禁用,请设置为 false

failOnError

  • 类型
type failOnError = boolean;
  • 默认值:true

如果存在任何错误,将导致模块构建失败。要禁用,请设置为 false

failOnWarning

  • 类型
type failOnWarning = boolean;
  • 默认值:false

当设置为 true 时,如果存在任何警告,将导致模块构建失败。

quiet

  • 类型
type quiet = boolean;
  • 默认值:false

当设置为 true 时,将仅处理和报告错误,并忽略警告。

outputReport

  • 类型
type outputReport =
  | boolean
  | {
      filePath?: string | undefined;
      formatter?:
        | (
            | string
            | ((results: Array<import('stylelint').LintResult>) => string)
          )
        | undefined;
    };
  • 默认值:false

将错误输出写入文件 - 例如,用于报告的 json 文件。

filePath 是相对于 webpack 配置的:output.path

您可以为输出文件传递不同的格式化程序。如果未传入任何格式化程序,将使用默认/已配置的格式化程序。

{
  filePath: 'path/to/file';
  formatter: 'json';
}

更新日志

更新日志

贡献

我们欢迎所有贡献!如果您是新用户,请在提交问题或拉取请求之前花一些时间阅读我们的贡献指南。

CONTRIBUTING

许可证

MIT

SvgChunkWebpackPlugin

GitHub Workflow Status (branch) Coverage Status Npm downloads

svg-chunk-webpack-plugin 根据 Webpack 的入口点创建优化的 SVG 精灵图。每个精灵图仅包含其入口点中列出的 SVG 依赖项,以改进代码拆分,即使是 SVG 文件也是如此。

该插件包含流行的 SVGO 包,用于生成干净和优化的 SVG 精灵图。

代码拆分是交付不含页面未使用内容的文件的关键。它已经存在于 CSS、Javascript 中,现在通过此插件也适用于 SVG 文件。

何时使用此插件

在多页面应用程序中,每个页面必须只包含其必要的依赖项。换句话说,它必须只包含由其入口点及其所有依赖项导入的 SVG 文件。

对于可重用组件,SVG 经常在所有项目中重复。现在,您可以创建一个全局 SVG 库,并且每个 Javascript 文件都可以轻松地从该库导入任何 SVG。由于 Webpack 编译,入口点依赖项会自动更新。

当您使用设计软件(如 Sketch 或 Illustrator)导出的 SVG 时,它们的源代码从未经过优化,并且通常包含注释、CSS 类,这可能会在它们之间造成冲突。该插件会在创建精灵图之前自动清理所有 SVG。

零配置

该插件无需配置即可工作,并已包含优化设置。有关高级用法,请参阅使用配置部分。

安装

该插件作为名为 svg-chunk-webpack-plugin 的包在 npmGithub 上提供。

npm install svg-chunk-webpack-plugin --save-dev
yarn add svg-chunk-webpack-plugin --dev

[!WARNING] 插件 svg-chunk-webpack-plugin@5 仅支持 ESM。 [!NOTE] 最低支持的 Node.js 版本为 16.20.0,Webpack 为 >=5.10.3

示例

该项目在 ./example 目录中包含一个极简示例。运行 npm run build:example 命令以执行 Webpack 示例并查看插件的实际实现。

基本用法

该插件将为每个入口点生成一个 SVG 精灵图。精灵图与所有其他资产一起构建在输出路径目录中。每个精灵图文件名都由其入口点名称组成(在下面的示例中,这将是 home.svg)。

首先,将加载器和插件添加到 Webpack 配置中。

[!WARNING] 加载器和插件需要协同工作。

webpack.config.js

import SvgChunkWebpackPlugin from 'svg-chunk-webpack-plugin';

export default {
  module: {
    rules: [
      {
        test: /\.svg$/,
        use: [
          {
            loader: SvgChunkWebpackPlugin.loader
          }
        ]
      }
    ]
  },
  plugins: [new SvgChunkWebpackPlugin()]
};

[!NOTE] 为了获得更大的灵活性和更好的性能,内联 SVG 文件更好。HTTP 请求更少,可以通过 CSS 属性更改样式,页面加载期间不会闪烁。

然后,在所需的页面中包含精灵图(在以下示例中,我们使用 Twig)。

home.html.twig

{{ include 'home.svg' }}

最后,使用 <use> 标签使用 SVG,如下例所示。将 <svg_name> 替换为 SVG 名称(不带扩展名)。

home.html.twig

<svg>
  <use href="#<svg_name>"></use>
</svg>

使用配置

加载器和插件接受配置以覆盖默认行为。

加载器

加载器配置允许个性化 SVGO 配置。SVGO 优化在加载器处理期间执行,以优化构建性能。

configFile

类型

type configFile = string | boolean;

默认值: path.resolve(opts.root, 'svgo.config.js')

告诉加载器是否加载自定义 SVGO 配置。自定义配置可以使用 configFile: false 禁用。

webpack.config.js

export default {
  module: {
    rules: [
      {
        test: /\.svg$/,
        loader: SvgChunkWebpackPlugin.loader,
        options: {
          configFile: './path/svgo.config.js'
        }
      }
    ]
  }
};

SVGO 自定义配置

SVGO 有一个默认预设用于优化 SVG 文件。有关详细信息,请参阅如何配置 svgo

svgo.config.js

export default {
  multipass: true,
  plugins: [
    {
      name: 'preset-default',
      params: {
        overrides: {
          inlineStyles: {
            onlyMatchedOnce: false
          },
          removeViewBox: false
        }
      }
    },
    {
      name: 'convertStyleToAttrs'
    }
  ]
};

插件

插件配置允许个性化精灵图设置。

filename

类型

type filename = string;

默认值: '[name].svg'

告诉插件是否个性化默认精灵图文件名。占位符 [name] 会自动替换为入口点名称。

webpack.config.js

export default {
  plugins: [
    new SvgChunkWebpackPlugin({
      filename: '[name].svg'
    })
  ]
};

[!NOTE] filename 参数与 Webpack 缓存占位符兼容,请参阅缓存部分。

svgstoreConfig

类型

type svgstoreConfig = object;

默认值: { cleanDefs: false, cleanSymbols: false, inline: true }

SVG 精灵图是使用 svgstore 包构建的。根据 svgstore 文档中可用的选项列表,根据您的需要更新参数。

webpack.config.js

export default {
  plugins: [
    new SvgChunkWebpackPlugin({
      svgstoreConfig: {
        svgAttrs: {
          'aria-hidden': true,
          style: 'position: absolute; width: 0; height: 0; overflow: hidden;'
        }
      }
    })
  ]
};

[!NOTE] 为避免 LinearGradient 冲突,请避免使用 display: none 属性,因为它会破坏 SVG 定义。

generateSpritesManifest

类型

type generateSpritesManifest = boolean;

默认值:false

告诉插件是否生成 sprites-manifest.json。JSON 文件包含入口点包含的所有 SVG 列表。

webpack.config.js

export default {
  plugins: [
    new SvgChunkWebpackPlugin({
      generateSpritesManifest: true
    })
  ]
};

generateSpritesPreview

类型

type generateSpritesPreview = boolean;

默认值:false

告诉插件是否生成 sprites-preview.html。HTML 预览包含入口点包含的所有 SVG 的显示列表,其中包含 SVG 概览和名称。请参阅示例的精灵图预览

webpack.config.js

export default {
  plugins: [
    new SvgChunkWebpackPlugin({
      generateSpritesPreview: true
    })
  ]
};

缓存

使用webpack 缓存,根据您的需求有几个占位符可用。如果 SVG 内联在页面中,此选项则无用。

[!NOTE] [contenthash] 占位符是最佳选择,因为它取决于精灵图内容。缓存占位符在构建性能方面开销较大,仅在生产模式下使用。

[contenthash]

[contenthash] 占位符将根据精灵图的内容添加唯一的哈希值。当精灵图的内容更改时,哈希值也会更改。

webpack.config.js

export default {
  plugins: [
    new SvgChunkWebpackPlugin({
      filename: '[name].[contenthash].svg'
    })
  ]
};

[fullhash]

[fullhash] 占位符将为每次构建添加唯一的哈希值。当编译构建更新时,哈希值也会更改。

webpack.config.js

export default {
  plugins: [
    new SvgChunkWebpackPlugin({
      filename: '[name].[fullhash].svg'
    })
  ]
};

许可证

svg-chunk-webpack-plugin 遵循 MIT 许可证

@yoriiis 用 ♥ 创建。

TerserWebpackPlugin

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(例如,通过 CLI 或 npm 脚本)。

关于源映射的注意事项

仅适用于 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 - 1os.availableParallelism() - 1(如果此函数受支持)。

注意

并行化可以显著加速您的构建,因此强烈推荐

警告

如果您使用 Circle CI 或任何其他不提供真实可用 CPU 数量的环境,则需要明确设置 CPU 数量以避免 Error: Call retries were exceeded(请参阅 #143#202)。

boolean

启用/禁用多进程并行运行。

webpack.config.js

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

number

启用多进程并行运行并设置并发运行的数量。

webpack.config.js

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

minify

类型

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 选项指定是否保留注释 - 即,可以保留一些注释(例如注释)同时提取其他注释,甚至保留已提取的注释。

boolean

启用/禁用提取注释。

webpack.config.js

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

string

提取 allsome(使用 /^\**!|@preserve|@license|@cc_on/i 正则表达式)注释。

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;

默认值: /*! For license information please see ${commentsFile} */

指向提取文件的横幅文本,它将添加到原始文件的顶部。

它可以是 false(无横幅)、String,或一个接受存储提取注释的文件名并返回 Stringfunction<(string) -> String>

横幅将被包装在注释中。

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.rust-lang.net.cn/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.org.cn/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
        },
      }),
    ],
  },
};

贡献

我们欢迎所有贡献!如果您是新用户,请在提交问题或拉取请求之前花一些时间阅读我们的贡献指南。

CONTRIBUTING

许可证

MIT

WatchIgnorePlugin

观察模式下,忽略指定的文件,即那些匹配提供路径或正则表达式的文件。

new webpack.WatchIgnorePlugin({ paths });

选项

  • paths (Array<string | RegExp>):应忽略的正则表达式或目录或文件的绝对路径列表。

1 贡献者

webpack