模块(Module)

这些选项决定了如何处理项目中的不同类型的模块

module.generator

5.12.0+

可以使用 module.generator 在一个地方配置所有生成器的选项。

webpack.config.js

module.exports = {
  module: {
    generator: {
      asset: {
        // asseet 模块的 generator 选项

        // 自定义 asset 模块的 publicPath,自 webpack 5.28.0 起可用
        publicPath: 'assets/',
      },
      'asset/inline': {
        // asset/内联模块的 generator 选项
      },
      'asset/resource': {
        // asset/资源模块的 generator 选项

        // 自定义 asset/resource 模块的 publicPath,自 webpack 5.28.0 起可用
        publicPath: 'assets/',
      },
      javascript: {
        // 该模块类型尚不支持 generator 选项
      },
      'javascript/auto': {
        // 同上
      },
      'javascript/dynamic': {
        // 同上
      },
      'javascript/esm': {
        // 同上
      },
      // 其他...
    },
  },
};

module.parser

5.12.0+

类似于 module.generator,你可以用 module.parser 在一个地方配置所有解析器的选项。

webpack.config.js

module.exports = {
  module: {
    parser: {
      asset: {
        // 资产模块的 parser 选项
      },
      'asset/inline': {
        // 该模块类型尚不支持 parser 选项
      },
      'asset/resource': {
        // 同上
      },
      'asset/source': {
        // 同上
      },
      javascript: {
        // javascript 模块的解析器选项
        // 例如,启用解析 require.ensure 语法的功能
        requireEnsure: true,
      },
      'javascript/auto': {
        // 同上
      },
      'javascript/dynamic': {
        // 同上
      },
      'javascript/esm': {
        // 同上
      },
      // 其他...
    },
  },
};

module.parser.javascript

JavaScript parser 的配置项。

module.exports = {
  module: {
    parser: {
      javascript: {
        // ...
        commonjsMagicComments: true,
      },
    },
  },
};

允许在 Rule.parser 中配置这些选项。也可以是特定模块。

module.parser.javascript.commonjsMagicComments

为 CommonJS 启用 魔法注释

  • 类型:boolean
  • 可用版本:5.17.0+
  • 示例:
    module.exports = {
      module: {
        parser: {
          javascript: {
            commonjsMagicComments: true,
          },
        },
      },
    };

请注意,目前只支持 webpackIgnore 注释:

const x = require(/* webpackIgnore: true */ 'x');

module.parser.javascript.url {#module.parser.javascript.url}

启用 new URL() 语法解析。

  • 类型:boolean = true | 'relative'
  • 示例:
    module.exports = {
      module: {
        parser: {
          javascript: {
            url: false, // disable parsing of `new URL()` syntax
          },
        },
      },
    };

自 webpack 5.23.0 起,module.parser.javascript.url'relative' 值可用。当使用 'relative' 时,webpack 将为 new URL() 语法生成相对的 URL,即结果 URL 中不包含根 URL:

<!-- with 'relative' -->
<img src='c43188443804f1b1f534.svg' />

<!-- without 'relative' -->
<img src='file:///path/to/project/dist/c43188443804f1b1f534.svg' />
  1. 当服务器不知道根 URL 时,这对 SSR(服务端渲染)很有用(而且可用节省一些字节)。为了使其相同,它也必须用于客户端构建。
  2. 这也适用于 SSG(静态网站生成器),mini-css-plugin 和 html-plugin 等通常需要进行服务端渲染。

module.noParse

RegExp [RegExp] function(resource) string [string]

防止 webpack 解析那些任何与给定正则表达式相匹配的文件。忽略的文件中 不应该含有 import, require, define 的调用,或任何其他导入机制。忽略大型的 library 可以提高构建性能。

webpack.config.js

module.exports = {
  //...
  module: {
    noParse: /jquery|lodash/,
  },
};
module.exports = {
  //...
  module: {
    noParse: (content) => /jquery|lodash/.test(content),
  },
};

module.unsafeCache

boolean function (module)

缓存模块请求的解析。module.unsafeCache 包含如下几个默认值:

  • 如果 cache 未被启用,则默认值为 false
  • 如果 cache 被启用,并且此模块的来自 node_modules,则值为 true,否则为 false

webpack.config.js

module.exports = {
  //...
  module: {
    unsafeCache: false,
  },
};

module.rules

[Rule]

创建模块时,匹配请求的规则数组。这些规则能够修改模块的创建方式。 这些规则能够对模块(module)应用 loader,或者修改解析器(parser)。

Rule

object

每个规则可以分为三部分 - 条件(condition),结果(result)和嵌套规则(nested rule)。

Rule 条件

条件有两种输入值:

  1. resource:资源文件的绝对路径。它已经根据 resolve 规则解析。

  2. issuer: 请求者的文件绝对路径。是导入时的位置。

例如:app.js 导入 './style.css',resource 是 /path/to/style.css. issuer 是 /path/to/app.js

在规则中,属性 test, include, excluderesource 对 resource 匹配,并且属性 issuer 对 issuer 匹配。

当使用多个条件时,所有条件都匹配。

Rule 结果

规则结果只在规则条件匹配时使用。

规则有两种输入值:

  1. 应用的 loader:应用在 resource 上的 loader 数组。
  2. Parser 选项:用于为模块创建解析器的选项对象。

这些属性会影响 loader:loader, options, use

也兼容这些属性:query, loaders

enforce 属性会影响 loader 种类。不论是普通的,前置的,后置的 loader。

parser 属性会影响 parser 选项。

嵌套的 Rule

可以使用属性 rulesoneOf 指定嵌套规则。

这些规则用于在规则条件(rule condition)匹配时进行取值。每个嵌套规则包含它自己的条件。

被解析的顺序基于以下规则:

  1. 父规则
  2. rules
  3. oneOf

Rule.enforce

string

可能的值有:"pre" | "post"

指定 loader 种类。没有值表示是普通 loader。

还有一个额外的种类"行内 loader",loader 被应用在 import/require 行内。

所有一个接一个地进入的 loader,都有两个阶段:

  1. Pitching 阶段: loader 上的 pitch 方法,按照 后置(post)、行内(inline)、普通(normal)、前置(pre) 的顺序调用。更多详细信息,请查看 Pitching Loader
  2. Normal 阶段: loader 上的 常规方法,按照 前置(pre)、普通(normal)、行内(inline)、后置(post) 的顺序调用。模块源码的转换, 发生在这个阶段。

所有普通 loader 可以通过在请求中加上 ! 前缀来忽略(覆盖)。

所有普通和前置 loader 可以通过在请求中加上 -! 前缀来忽略(覆盖)。

所有普通,后置和前置 loader 可以通过在请求中加上 !! 前缀来忽略(覆盖)。

// 禁用普通 loaders
import { a } from '!./file1.js';

// 禁用前置和普通 loaders
import { b } from '-!./file2.js';

// 禁用所有的 laoders
import { c } from '!!./file3.js';

不应使用内联 loader 和 ! 前缀,因为它是非标准的。它们可能会被 loader 生成代码使用。

Rule.exclude

排除所有符合条件的模块。如果你提供了 Rule.exclude 选项,就不能再提供 Rule.resource。详细请查看 Rule.resourceCondition.exclude

Rule.include

引入符合以下任何条件的模块。如果你提供了 Rule.include 选项,就不能再提供 Rule.resource。详细请查看 Rule.resourceCondition.include

Rule.issuer

一个条件,用来与被发出的 request 对应的模块项匹配。在以下示例中,a.js request 的发出者(issuer) 是 index.js 文件的路径。

index.js

import A from './a.js';

这个选项可以用来将 loader 应用到一个特定模块或一组模块的依赖中。

Rule.issuerLayer

允许按 issuer 的 layer 进行过滤/匹配。

webpack.config.js

module.exports = {
  // ...
  module: {
    rules: [
      {
        issuerLayer: 'other-layer',
      },
    ],
  },
};

Rule.layer

string

指定模块应放置在哪个 layer。

webpack.config.js

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /module-layer-change/,
        layer: 'layer',
      },
    ],
  },
};

Rule.loader

Rule.loaderRule.use: [ { loader } ] 的简写。详细请查看 Rule.useUseEntry.loader

Rule.loaders

Rule.loadersRule.use 的别名。详细请查看 Rule.use

Rule.mimetype

你可以使用 mimetype 使 rules 配置与 data 的 uri 进行匹配。

webpack.config.js

module.exports = {
  // ...
  module: {
    rules: [
      {
        mimetype: 'application/json',
        type: 'json',
      },
    ],
  },
};

mimetype 已默认包含了 application/jsontext/javascriptapplication/javascriptapplication/node 以及 application/wasm

Rule.oneOf

规则数组,当规则匹配时,只使用第一个匹配规则。

webpack.config.js

module.exports = {
  //...
  module: {
    rules: [
      {
        test: /\\.css$/,
        oneOf: [
          {
            resourceQuery: /inline/, // foo.css?inline
            use: 'url-loader',
          },
          {
            resourceQuery: /external/, // foo.css?external
            use: 'file-loader',
          },
        ],
      },
    ],
  },
};

Rule.options / Rule.query

Rule.optionsRule.queryRule.use: [ { options } ] 的简写。详细请查看 Rule.useUseEntry.options

Rule.parser

解析选项对象。所有应用的解析选项都将合并。

解析器(parser)可以查阅这些选项,并相应地禁用或重新配置。大多数默认插件, 会如下解释值:

  • 将选项设置为 false,将禁用解析器。
  • 将选项设置为 true,或不修改将其保留为 undefined,可以启用解析器。

然而,一些解析器(parser)插件可能不光只接收一个布尔值。例如,内部的 NodeStuffPlugin 插件,可以接收一个对象,而不是 true, 来为特定的规则添加额外的选项。

示例(默认的插件解析器选项):

module.exports = {
  //...
  module: {
    rules: [
      {
        //...
        parser: {
          amd: false, // 禁用 AMD
          commonjs: false, // 禁用 CommonJS
          system: false, // 禁用 SystemJS
          harmony: false, // 禁用 ES2015 Harmony import/export
          requireInclude: false, // 禁用 require.include
          requireEnsure: false, // 禁用 require.ensure
          requireContext: false, // 禁用 require.context
          browserify: false, // 禁用特殊处理的 browserify bundle
          requireJs: false, // 禁用 requirejs.*
          node: false, // 禁用 __dirname, __filename, module, require.extensions, require.main, 等。
          node: {...}, // 在模块级别(module level)上重新配置 [node](/configuration/node) 层(layer)
          worker: ["default from web-worker", "..."] // 自定义 WebWorker 对 JavaScript 的处理,其中 "..." 为默认值。
        }
      }
    ]
  }
}

如果 Rule.type 的值为 asset,那么 Rules.parser 选项可能是一个对象或一个函数,其作用可能是将文件内容编码为 Base64,还可能是将其当做单独文件 emit 到输出目录。

如果 Rule.type 的值为 assetasset/inline,那么 Rule.generator 选项可能是一个描述模块源编码方式的对象,还可能是一个通过自定义算法对模块源代码进行编码的函数。

更多信息及用例请查阅 Asset 模块指南

Rule.parser.dataUrlCondition

object = { maxSize number = 8096 } function (source, { filename, module }) => boolean

如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。

webpack.config.js

module.exports = {
  //...
  module: {
    rules: [
      {
        //...
        parser: {
          dataUrlCondition: {
            maxSize: 4 * 1024,
          },
        },
      },
    ],
  },
};

当提供函数时,返回 true 值时告知 webpack 将模块作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。

webpack.config.js

module.exports = {
  //...
  module: {
    rules: [
      {
        //...
        parser: {
          dataUrlCondition: (source, { filename, module }) => {
            const content = source.toString();
            return content.includes('some marker');
          },
        },
      },
    ],
  },
};

Rule.generator

Rule.generator.dataUrl

object = { encoding string = 'base64' | false, mimetype string = undefined | false } function (content, { filename, module }) => string

Rule.generator.dataUrl 被用作一个对象,你可以配置两个属性:

  • encoding: 当被设置为'base64',模块源码会用 Baes64 算法 编码。设置 encoding 为 false,会禁用编码。
  • mimetype: 为数据链接(data URI)设置的一个 mimetype 值。默认根据模块资源后缀设置。

webpack.config.js

module.exports = {
  //...
  module: {
    rules: [
      {
        //...
        generator: {
          dataUrl: {
            encoding: 'base64',
            mimetype: 'mimetype/png',
          },
        },
      },
    ],
  },
};

当被作为一个函数使用,它必须为每个模块执行且并须返回一个数据链接(data URI)字符串。

module.exports = {
  //...
  module: {
    rules: [
      {
        //...
        generator: {
          dataUrl: (content) => {
            const svgToMiniDataURI = require('mini-svg-data-uri');
            if (typeof content !== 'string') {
              content = content.toString();
            }
            return svgToMiniDataURI(content);
          },
        },
      },
    ],
  },
};

Rule.generator.emit

配置不从 Asset Modules 写入资源文件, 你可能会在 SSR 中使用它。

  • 类型:boolean = true

  • 可用版本:5.25.0+

  • 示例:

    module.exports = {
      // …
      module: {
        rules: [
          {
            test: /\.png$/i,
            type: 'asset/resource',
            generator: {
              emit: false,
            },
          },
        ],
      },
    };

Rule.generator.filename

对某些特定的规则而言与 output.assetModuleFilename 相同. 覆盖了 output.assetModuleFilename 选项并且仅与 assetasset/resource 模块类型一同起作用。

webpack.config.js

module.exports = {
  //...
  output: {
    assetModuleFilename: 'images/[hash][ext][query]',
  },
  module: {
    rules: [
      {
        test: /\.png/,
        type: 'asset/resource',
      },
      {
        test: /\.html/,
        type: 'asset/resource',
        generator: {
          filename: 'static/[hash][ext]',
        },
      },
    ],
  },
};

Rule.generator.publicPath

对指定的资源模式指定 publicPath

  • 类型:string | ((pathData: PathData, assetInfo?: AssetInfo) => string)
  • 可用版本:5.28.0+
module.exports = {
  //...
  output: {
    publicPath: 'static/',
  },
  module: {
    rules: [
      {
        test: /\.png$/i,
        type: 'asset/resource',
        generator: {
          publicPath: 'assets/',
        },
      },
    ],
  },
};

Rule.resource

条件会匹配 resource。在 Rule 条件 中查阅详情。

Rule.resourceQuery

与资源查询相匹配的 Condition。此选项用于测试请求字符串的查询部分(即从问号开始)。如果你需要通过 import Foo from './foo.css?inline' 导入 Foo,则需符合以下条件:

webpack.config.js

module.exports = {
  //...
  module: {
    rules: [
      {
        test: /\\.css$/,
        resourceQuery: /inline/,
        use: 'url-loader',
      },
    ],
  },
};

Rule.parser.parse

function(input) => string | object

如果 Rule.type 被设置成 'json',那么 Rules.parser.parse 选择可能会是一个方法,该方法实现自定义的逻辑,以解析模块的源和并将它转换成 JavaScript 对象。 它可能在没有特定加载器的时候,对将 toml, yaml 和其它非 JSON 文件导入成导入非常有用:

webpack.config.js

const toml = require('toml');

module.exports = {
  //...
  module: {
    rules: [
      {
        test: /\.toml/,
        type: 'json',
        parser: {
          parse: toml.parse,
        },
      },
    ],
  },
};

Rule.rules

规则数组,当规则匹配时使用。

Rule.scheme

匹配使用的 schema,例如 datahttp

  • 类型:string | RegExp | ((value: string) => boolean) | RuleSetLogicalConditions | RuleSetCondition[]
  • 可用:5.38.0+

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        scheme: 'data',
        type: 'asset/resource',
      },
    ],
  },
};

Rule.sideEffects

bool

表明模块的哪一部份包含副作用。详情参阅 Tree Shaking

Rule.test

引入所有通过断言测试的模块。如果你提供了一个 Rule.test 选项,就不能再提供 Rule.resource。详细请查看 Rule.resourceCondition.test

Rule.type

string

可设置值: 'javascript/auto' | 'javascript/dynamic' | 'javascript/esm' | 'json' | 'webassembly/sync' | 'webassembly/async' | 'asset' | 'asset/source' | 'asset/resource' | 'asset/inline'

Rule.type 设置类型用于匹配模块。它防止了 defaultRules 和它们的默认导入行为发生。例如,如果你想 通过自定义 loader 加载一个 .json 文件,你会需要将 type 设置为 javascript/auto 以绕过 webpack 内置的 json 导入。 (详参v4.0 更新日志

webpack.config.js

module.exports = {
  //...
  module: {
    rules: [
      //...
      {
        test: /\\.json$/,
        type: 'javascript/auto',
        loader: 'custom-json-loader',
      },
    ],
  },
};

关于 asset* 类型详参 资源模块指南

Rule.use

[UseEntry] function(info)

[UseEntry]

Rule.use 可以是一个应用于模块的 UseEntries 数组。每个入口(entry)指定使用一个 loader。

传递字符串(如:use: [ 'style-loader' ])是 loader 属性的简写方式(如:use: [ { loader: 'style-loader'} ])。

Loaders 可以通过传入多个 loaders 以达到链式调用的效果,它们会从右到左被应用(从最后到最先配置)。

webpack.config.js

module.exports = {
  //...
  module: {
    rules: [
      {
        //...
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
            },
          },
          {
            loader: 'less-loader',
            options: {
              noIeCompat: true,
            },
          },
        ],
      },
    ],
  },
};

function(info)

Rule.use 也可以是一个函数,接受对象参数,描述被加载的模块,而且必须 返回 UseEntry 元素的数组。

info 对象参数有以下的字段:

  • compiler: 当前 webpack 的编译器(可以是 undefined 值)
  • issuer: 模块的路径,该元素正在导入一个被加载的模块(resource)
  • realResource: 总会是被加载模块的路径
  • resource: 被加载的模块路径,它常常与 realResource 相等,只有当资源名称被 request 字符串中的 !=! 覆盖时才不相等

相同的作为数组的快捷方式可以用作返回值(如 use: [ 'style-loader' ])。

webpack.config.js

module.exports = {
  //...
  module: {
    rules: [
      {
        use: (info) => [
          {
            loader: 'custom-svg-loader',
          },
          {
            loader: 'svgo-loader',
            options: {
              plugins: [
                {
                  cleanupIDs: {
                    prefix: basename(info.resource),
                  },
                },
              ],
            },
          },
        ],
      },
    ],
  },
};

参参 UseEntry

Rule.resolve

模块解析可以在模块层被配置。resolve 配置页面可查看所有可用的配置。 所有被应用的 resolve 选项被更高层级的resolve配置合并。

例如,假设我们有一个入口文件在 ./src/index.js, ./src/footer/default.js 和一个 ./src/footer/overridden.js, 用以论证模块层级的解析。

./src/index.js

import footer from 'footer';
console.log(footer);

./src/footer/default.js

export default 'default footer';

./src/footer/overridden.js

export default 'overridden footer';

webpack.js.org

module.exports = {
  resolve: {
    alias: {
      footer: './footer/default.js',
    },
  },
};

当用该配置创建一个包,console.log(footer) 会输出 'default footer'。让我们为 .js 文件设置 Rule.resolve,以及 footer 作为 overridden.js 的别名。

webpack.js.org

module.exports = {
  resolve: {
    alias: {
      footer: './footer/default.js',
    },
  },
  module: {
    rules: [
      {
        resolve: {
          alias: {
            footer: './footer/overridden.js',
          },
        },
      },
    ],
  },
};

当用该配置创建一个包,console.log(footer) 会输出 'overridden footer'。

resolve.fullySpecified

boolean = true

启用后,你若在 .mjs 文件或其他 .js 文件中导入模块,并且它们最近的 package.json 中包含 "type" 字段,其值为 "module"时,你应为此文件提供扩展名,否则 webpack 会提示 Module not found 的错误且编译失败。并且 webpack 不会解析 resolve.mainFiles 中定义的文件目录,你必须自己指定文件名。

webpack.config.js

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.m?js$/,
        resolve: {
          fullySpecified: false, // disable the behaviour
        },
      },
    ],
  },
};

条件

条件可以是这些之一:

  • 字符串:匹配输入必须以提供的字符串开始。是的。目录绝对路径或文件绝对路径。
  • 正则表达式:test 输入值。
  • 函数:调用输入的函数,必须返回一个真值(truthy value)以匹配。
  • 条件数组:至少一个匹配条件。
  • 对象:匹配所有属性。每个属性都有一个定义行为。

{ and: [Condition] }:必须匹配数组中的所有条件

{ or: [Condition] }:匹配数组中任何一个条件

{ not: [Condition] }:必须排除这个条件

示例:

const path = require('path');

module.exports = {
  //...
  module: {
    rules: [
      {
        test: /\\.css$/,
        include: [
          path.resolve(__dirname, 'app/styles'),
          path.resolve(__dirname, 'vendor/styles'),
        ],
      },
    ],
  },
};

UseEntry

object function(info)

object

必须有一个 loader 属性是字符串。它使用 loader 解析选项(resolveLoader),相对于配置中的 context 来解析。

可以有一个 options 属性为字符串或对象。值可以传递到 loader 中,将其理解为 loader 选项。

由于兼容性原因,也可能有 query 属性,它是 options 属性的别名。使用 options 属性替代。

注意,webpack 需要生成资源和所有 loader 的独立模块标识,包括选项。 它尝试对选项对象使用 JSON.stringify。这在 99.9% 的情况下是可以的, 但是如果将相同的 loader 应用于相同资源的不同选项,并且选项具有一些带字符的值,则可能不是唯一的。

如果选项对象不被字符化(例如循环 JSON),它也会中断。因此,你可以在选项对象使用 ident 属性, 作为唯一标识符。

webpack.config.js

module.exports = {
  //...
  module: {
    rules: [
      {
        loader: 'css-loader',
        options: {
          modules: true,
        },
      },
    ],
  },
};

function(info)

UseEntry 也可以是一个函数,接受对象参数,描述被加载的模块,而且必须返回一个参数对象。这可用于按模块更改 loader 选项。

info 对象参数有以下的字段:

  • compiler: 当前 webpack 的编译器(可以是 undefined 值)
  • issuer: 模块的路径,该元素正在导入一个被加载的模块(resource)
  • realResource: 总会是被加载模块的路径
  • resource: 被加载的模块路径,它常常与 realResource 相等,只有当资源名称被 request 字符串中的 !=! 覆盖时才不相等

webpack.config.js

module.exports = {
  //...
  module: {
    rules: [
      {
        loader: 'file-loader',
        options: {
          outputPath: 'svgs',
        },
      },
      (info) => ({
        loader: 'svgo-loader',
        options: {
          plugins: [
            {
              cleanupIDs: { prefix: basename(info.resource) },
            },
          ],
        },
      }),
    ],
  },
};

模块上下文(Module Contexts)

避免使用这些选项,因为它们 已废弃,并将很快删除。

这些选项描述了当遇到动态依赖时,创建上下文的默认设置。

例如,未知的(unknown) 动态依赖:require

例如,表达式(expr) 动态依赖:require(expr)

例如,包裹的(wrapped) 动态依赖:require('./templates/' + expr)

以下是其默认值的可用选项

webpack.config.js

module.exports = {
  //...
  module: {
    exprContextCritical: true,
    exprContextRecursive: true,
    exprContextRegExp: false,
    exprContextRequest: '.',
    unknownContextCritical: true,
    unknownContextRecursive: true,
    unknownContextRegExp: false,
    unknownContextRequest: '.',
    wrappedContextCritical: false,
    wrappedContextRecursive: true,
    wrappedContextRegExp: /.*/,
    strictExportPresence: false, // since webpack 2.3.0
  },
};

几个用例:

  • 动态依赖的警告:wrappedContextCritical: true
  • require(expr) 应该包含整个目录:exprContextRegExp: /^\.\//
  • require("./templates/" + expr) 不应该包含默认子目录:wrappedContextRecursive: false
  • strictExportPresence 将缺失的导出提示成错误而不是警告
  • 为部分动态依赖项设置内部正则表达式:wrappedContextRegExp: /\\.\\*/