mode
type: string
模式配置,webpack 可根据不同的模式选择不同的 内置优化过程。
production: "生产模式"。 当前模式下,部分配置项的默认值如下:
-
devTool 配置项的值为 false,不生成 .map 文件 ;
-
cache 配置项的值为 false,即 webpack 上一次编译生成的 modules、chunks 不被缓存,每次编译的时候需要重新生成 modules、chunks;
-
output.pathinfo 配置项的值为 false, ***;
-
optimization.flagIncludedChunks 配置项的值为 true,用于标记 子chunk, 详见下面描述;
-
optimization.occurrenceOrder 配置项的值为 true, 告诉 webpack 找出 module 的顺序,导致最小的初始包(仅字面意思,未理解);
-
optimization.sideEffects 配置项的值默认为 true, 用于移除 JavaScript上下文 中的 未引用代码(dead-code);
-
optimization.usedExports 配置项的值为 true, 告诉 webpack 确定每个 module 已使用的导出, 为 使用的导出 生成 导出;
-
optimization.concatenateModules 配置项的值为 true, 用于连接多个module为一个module;
-
optimization.splitChunks.minSize 配置项的值为 30kb,如果将 被分离出的chunk的大小 小于 minSize 值, 代码分离失败;
-
optimization.splitChunks.maxAsyncRequests 配置项的值为 5, 即按序加载时允许的最大并行请求数为 5, 否则代码分离会失败;
-
optimization.splitChunks.maxInitialRequests 配置项的值为3,即入口处的最大并行请求数为 3, 否则代码分离失败;
-
optimization.noEmitOnErrors 的值为 true,如果编译错误,不输出打包文件(??);
-
optimization.minimize 配置项的值为 true,对打包文件进行 压缩、混淆;
development: "开发模式"。当前模式下,部分配置项的默认值如下:
-
devTool 配置项的值默认为 "eval", 使用 eval() 包裹模块代码;
-
cache 配置项的值默认为 true。 webpack 上一次编译生成的 modules、chunks 都会缓存在 内存 中,当源文件发生变化重新编译构建模块依赖图时,如果模块对应的文件没有变化,则直接使用内存中缓存的 module,大大的减少编译时间;
-
output.pathinfo 配置项的值为 true, ***;
-
optimization.splitChunks.maxAsyncRequests 配置项的值为 Infinity,对按需加载时允许的最大并行请求数不做限制;
-
optimization.splitChunks.maxInitialRequests 配置项的值为 Infinity,对入口处允许的最大并行请求数不做限制;
-
optimization.splitChunks.minSize 配置项的值为 10kb,如果将 被分离出的chunk的大小 小于 minSize 值, 代码分离失效;
-
optimization.namedModules 配置项的值为 true,打包文件中以 模块源文件的路径(url) 作为 模块标识符;
-
optimization.namedChunks 配置项的值为 true,打包文件中以 chunk的名称 作为 chunk标识符;
如果未配置 mode, 默认情况下为 "production"。
context
type: string
基础目录,绝对路径,用于从配置中解析 入口起点(entry point) 和 loader。
context: path.resolve(__dirname, '../')
entry
type: string | [string] | object { : string | [string] } | function
应用程序的入口。 从这个起点开始,应用程序启动执行。
如果 entry 配置项的值的类型为 string, 对应 单页面单入口应用。在编译过程中, 生成 一个模块依赖关系图。
如果 entry 配置项的值的类型为 [string], 对应 单页面多入口应用。应用程序启动时,数组中的入口文件按序执行。在编译过程中,生成 一个模块依赖关系图。
如果 entry 配置项的值为 object, 对应 多页面(单入口/多入口)应用。在编译过程中,生成 多个模块依赖关系图。
如果 entry 配置项的值的类型为 function,则是 动态入口(待研究)。
Resolve
type: object
Resolve配置项 可以设置 源文件、npm包 如何被 解析。
webpack 在 构建依赖关系图 时会通过 resolve 配置项 解析模块的url 来获取 模块源文件的绝对地址。 通过 源文件的绝对地址,读取源文件的内容,然后使用 解析器(parser) 解析源文件的代码结构,获取 依赖模块。
此外,webpack 使用 loader 处理 源文件 时,也会通过 resolve 配置项 解析 loader包 的 入口文件 的绝对地址,然后使用 入口文件 提供的方法处理 源文件 内容。
webpack 会提供 合理的默认值,如果不满足需要,我们也可以自己设置 Resolve配置项。
-
alias | object
创建 import 或 require 的别名, 确保模块引入变的更加简单。
在 创建模块 的时候, webpack 会解析模块的 请求路径(request path)。如果 请求路径 中使用了 别名 , webpack 会根据 resolve.alias 配置项,将 请求路径(request path) 转化为 源文件的绝对路径。
用法详见 官网。
-
aliasFields | [string]
指定一个字段,根据此规范进行解析, 默认值为 ["browser"]。
-
descriptionFiles
用于描述的 JSON 文件,默认值为 ["package.json"]
使用npm包时, 可以通过 package.json文件 获取 npm包 的 入口文件。
-
enforceExtension | boolean
是否 强制需要文件扩展名。 默认值为 false, 即 不需要。
如果值为 true,则 不允许无扩展名文件,否则 报错。
// main.js import { func1 } from '../util.1.js' import { func2 } from '../util.2' // enforceExtension:true, 解析模块路径会报错
-
enforceModuleExtension | boolean
对模块是否需要使用的扩展, 默认为 false。
-
extensions | [string]
可 自动解析的扩展, 默认值为 [".wasm", ".mjs", ".js", ".json"]
-
mainFields | [string]
当从 npm包 中导入 模块 时(例如,import * as D3 from "d3"),此选项将决定在 package.json 中使用 哪个字段 导入模块。
如果 target配置项 的值为 webworker, web 或者 没有指定,默认值为:["browser", "module", "main"]。
对于 其他任意的 target(包括 node),默认值为:["module", "main"]。
用法详见 官网。
-
mainFiles | [string]
解析目录时要使用的文件名,默认值: ["index"]。
-
modules | [string]
告诉 webpack 解析模块时应该搜索的 目录。
数组中指定的目录的 优先级: 高 -> 低。
默认值: ["node_modules"]。
webpack 在解析 npm包 的路径时,会在工作目录下的 node_modules 目录中查找。
用法详见 官网。
-
unsafeCache | regex | array | boolean
是否启用 缓存, 默认值为 true。
如果值为 true,启用 ; 如果值为 false, 禁用。
webpack 在解析 模块、npm包入口文件 路径时,会把 解析结果(文件绝对路径、描述文件package.json信息等) 缓存起来。等到下次解析 相同模块、npm包 时, 直接使用缓存。
-
cacheWithContext | boolean
如果启用了 unsafeCache,缓存解析结果的 cache 中 key 中会包含 context配置项 指定的信息。
默认值为 false。
-
plugins | [object]
使用的额外的 解析插件。
-
symlinks | boolean
是否将符号链接(symlink)解析到它们的符号链接位置(symlink location)。
默认值为 true。
暂未理解。
-
cachePredicate | function
指定一个 自定义函数,用于判断 源文件、npm包 的 解析结果 是否会被 缓存。
如果返回 false, 即使 unsafeCache 的值为 true, 解析结果也 不会被缓存。
自定义函数使用时会传入一个带有 请求信息 的 对象。
resolve: { cachePredicate: function(params) { // params.path 对应 context 配置项的值 // params.request 对应 请求path : './src/utils/util.1.js' return /\/src/.test(params.request) } }
resolveLoader
type: object
resolveLoader配置项 用法和 resolve配置项 完全一致, 区别是它 仅 用于 解析webpack的loader包。
即当 webpack 需要解析 loader包 的 入口文件 时,才会用到 resolveLoader配置项。
默认值:
{
cacheWithContext: false,
unsafeCache: true,
extensions: ['.js', '.json'],
mainFields: ['loader', 'main'],
mainFiles: ['index']
}
-
moduleExtensions | ['string']
解析 loader 时,用到 扩展名(extensions)/后缀(suffixes)。
具体用法如下:
{ module: { rules: [{ test: /\.(css|scss)$/, loaders: ['css'] }] }, resolveLoader: { moduleExtensions: ['-loader'] } ... }
module
type: object
用于处理项目中的 不同类型(.js、.css、.sass、.vue、.png ...) 的模块。
-
noParse | RegExp | [RegExp] | function
在构建 依赖关系图 时,webpack 会读取 模块源文件 的内容,然后 将源文件内容解析成一颗AST树。 分析 AST树,获取模块的 依赖 的 静态模块、懒加载模块、全局变量。
如果 模块的url(绝对路径) 匹配 noParse配置项指定的表达式, 那么 模块对应的源文件的代码结构 不会被解析。 不解析大型的library可以 提高构建性能。
不解析的模块源文件中不应该含有 import、require、define、url、全局变量 等。
用法:
module: { noParse: /vue|loadsh/ } module: { // content 为模块源文件的绝对路径 // vue-D:\study\demo\webpack\webpack-4-demo\node_modules\_vue@2.6.10@vue\dist\vue.runtime.esm.js" noParse: function(content) { return /vue|loadsh/.test(content) } }
效果:
// noParse: /vue/ (window["webpackJsonp"] = window["webpackJsonp"] || []).push([["vendors-main"],{ "./node_modules/_vue@2.6.10@vue/dist/vue.runtime.esm.js": (function(module, __webpack_exports__, __webpack_require__) {...}) }]) // 不使用 noParse (window["webpackJsonp"] = window["webpackJsonp"] || []).push([["vendors-main"],{ "./node_modules/_process@0.11.10@process/browser.js": (function(module, exports) {...}), "./node_modules/_setimmediate@1.0.5@setimmediate/setImmediate.js": (function(module, exports, __webpack_require__) {...}), "./node_modules/_timers-browserify@2.0.10@timers-browserify/main.js": (function(module, exports, __webpack_require__) {...}), "./node_modules/_vue@2.6.10@vue/dist/vue.runtime.esm.js": (function(module, __webpack_exports__, __webpack_require__) {...}), "./node_modules/_webpack@4.34.0@webpack/buildin/global.js": (function(module, exports) {...}) }])
如果 不使用noParse, vue.js 在构建 依赖关系图 时会被 解析为AST树,获取 vue 依赖的全局变量 global、setImmediate,然后构建相应的模块。"browser"、"setImmediate"、"main"、"global" 就是解析vue模块生成的模块。如果使用了 noParse: /vue/, vue模块不会被解析,全局变量对应的模块也不会生成。
-
rules | [object]
模块(module) 构建时, 使用 源文件url(绝对路径) 来匹配 module.rules 中的规则,为模块选择 处理源文件需要的 loader 和 解析源文件内容需要的 parser。
module.rules 是一个 array, rules 中的每一个 rule 是一个 object。
每一个 规则(rule) 可以分成三部分:条件(conditions)、结果(results) 和 嵌套规则(nested rules)。
条件(conditions) 的 输入值 有两种:
-
resource - 源文件的path(绝对路径);
-
issuer - 发布者( issuer - A中引入B,则A是B的issuer )的path(绝对路径);
如果 module 的 resource属性 匹配 rule.test 、rule.include 、rule.exclude、rule.resource, 或者 module 的 issuer 属性匹配 rule.issuer, 则 模块匹配当前规则rule, 可以使用 rule中的loader 处理模块。
结果(results) 的 输出值 有两个:
-
loader - 应用在 resource 上的 loader数组,将 源文件 转化为 浏览器可识别的文件类型;
-
parser option - 用于构建parser(将源文件代码解析为AST结构, 分析源文件的依赖);
嵌套规则(nested rules) :
可以使用属性 rules 和 oneOf 指定 嵌套规则。这些规则用于在 规则条件(rule condition)匹配 时进行取值。
一个 模块 只有满足 规则(rule) 的 条件(conditions),才能拿到 规则(rule)对应的结果(loader、parser options) 来 处理模块。
rule 的配置项如下:
-
resource | object
规则(rule) 的 条件(condition)配置项。如果 模块path(绝对路径) 符合 条件(condition),将使用 当前规则对应的loaders处理模块。
-
test | RegExp | string | function | [RegExp] | [string] | [function]
条件配置项,不考虑其他配置项的情况下,如果 模块path(绝对路径)满足 test 指定条件,则 匹配 当前规则。
test 的值一般为 正则表达式,通过 文件后缀 来判断模块是否匹配规则。
test: /\.css$/
test 的值也可以是 string, 如果 模块path(绝对路径)包含test指定的值(path.indexOf(test) === 0), 则模块匹配当前规则。
// test的值必须是绝对路径 test: path.resolve(__dirname, '../src') // 由于模块path是绝对路径,path.indexOf('src') !== 0, 不匹配 test: 'src'
如果 test 的值是 string 类型,则必须是 绝对路径。
test 的值也可以是 function,用户可 自定义条件。
test: function(request) { return /\.css$/.test(request) }
如果 test 的值是一个 array( [RegExp]、[string]、[function] ), array 中 条件 之间的关系为 或,只要 模块path(绝对路径) 满足 test中的某一个条件,那么模块就匹配当前规则。
-
include | RegExp | string | function | [RegExp] | [string] | [function]
条件配置项,不考虑其他配置项的情况下,如果 模块path(绝对路径)满足指定条件,则 匹配 当前规则, 用法和test完全一致。
-
exclude | RegExp | string | function | [RegExp] | [string] | [function]
条件配置项,不考虑其他配置项的情况下,如果 模块path(绝对路径)不满足指定条件,则 匹配 当前规则。
exclude的用法和test基本相同, 唯一的区别是如果 exclude 的值是一个 array( [RegExp]、[string]、[function] ), array 中 条件 之间的关系为 且,只有 模块path(绝对路径) 不满足 exclude中的所有条件,模块才能匹配当前规则。
在实际应用中, test 一般配合 include 或者 exclude 使用,test指定文件类型, include或者exclude指定范围。
另外,test、include、exclude 之间的关系是 且,模块path(绝对路径)必须全部满足,才能匹配当前规则。
-
-
test
Rule.test 是 Rule.resource.test 的 缩写。
注意,使用 Rule.test 之后就不能再使用 Rule.resource,否则会 报错。
// 这种也是不允许的 { test: /\.js$/, resource: { include: [path.resolve(__dirname, '../src')] } }
-
include
Rule.include 是 Rule.resource.include 的 缩写。
注意,使用 Rule.include 之后就不能再使用 Rule.resource,否则会 报错
-
exclude
Rule.exclude 是 Rule.resource.exclude 的 缩写。
注意,使用 Rule.exclude 之后就不能再使用 Rule.resource,否则会 报错
-
issuer
不考虑其他配置项的情况下,如果 模块的发布者(issuer)的path(绝对路径) 满足 issuer 指定的条件,那么模块匹配当前规则。
即,模块B 被 模块A 引用, 如果 模块A(issuer) 满足 issuer 指定的条件, 那么 模块B 匹配当前规则。
这个选项可以用来将 loader 应用到一个特定模块或一组模块的依赖中
Rule.issuer 的用法和 Rule.test 完全一致。
-
resourceQuery
不考虑其他配置项的情况下,如果 模块path(绝对路径) 的 query参数 满足 resourceQuery 指定的条件, 那么模块匹配当前规则。
// main.js import A from './styles/style.css?inline' // webpackConfig.js module: { rules: [{ test: /\.css$/, resourceQuery: /inline/ // resourceQuery: 'inline' '?inline'.indexOf('inline') !== 0, 匹配失败 }] }
resourceQuery配置项 的用法和 test配置项 的用法 完全一样。
需要注意的是,在匹配的时候,会拿 模块path(绝对路径) 的 query 部分, 即 '?inline', 与 resourceQuery 对应的值做比较。 如果 resourceQuery 的值为 string,匹配规则为 query.indexOf(resourceQuery) === 0。resourceQuery 提供的值一定要 精确,才能匹配成功。
一般情况下, resourceQuery配置项 的值为 RegExp 或者 function。
-
use | object | [object] | string | [string] | function
指定应用于模块的 loader。
当 模块path(绝对路径) 匹配 规则条件(rule conditions) 时,可使用 use配置项指定的loaders 处理模块。
use配置项 的值可以是一个 object,具体属性如下:
-
loader | string
指定使用的 loader 的 名称, 例 loader: 'css-loader'。
loader 属性是 必要属性, 缺少会报错。
-
options | object
指定 loader 的 配置项,调整loader的行为。
-
query | object
指定 loader 的 配置项,调整loader的行为。
query配置项 的作用和 options 一样, 二者只需一个。同时存在会报错。
use: { loader: 'css-loader', options: { minimize: true } }
use配置项 的值也可以是一个 string, 如:
use: 'css-loader?minimize=true' // 在 webpack 处理过程中,会转化为一个 object { loader: 'css-loader', options: { minimize: true } }
use配置项 的值也可以是一个 [object], 每一个 object 含有 loader、 options/query 属性;
use: [{ loader: 'style-loader' }, { loader: 'css-loader', options: { minimize: true } }]
use配置项 的值也可以是一个 **[string]****, 如:
use: ['style-loader', 'css-loader']
如果 use 配置项的值为 array,即 存在多个loader,webpack会倒序使用loader处理模块。例如, use: ['style-loader', 'css-loader'], webpack 会先使用 css-loader,再使用 style-loader。
use配置项 的值也可以是一个 function,具体使用参照 官网。
-
-
loader | string
rule.loader 是 rule.use: [{loader}] 的缩写。
loader: 'css-loader' // 相当于 use: [{loader: ‘css-loader’}] loader: 'style-loader!css-loader' // 相当于 use: [{loader: ‘style-loader’}, {loader: ‘css-loader’}]
-
loaders
rule.loaders 是 rule.use 的别名,用法和 rule.use 完全一致。
rule.loader、rule.loaders 只需要提供一个就够了,否则会报错。
-
options | object
指定 loader 的 配置项,调整loader的行为。
options配置项必须配合loader配置项 使用, 否则报错。
rules: [{ test: /\.css$/, loader: 'css-loader', options: { minimize: true } }] // 等价于: rules: [{ test: /\.css$/, use: [{ loader: 'css-loader', options: { minimize: true } }] }]
如果loader 为 'style-loader!css-loader' 这种格式, 使用options会报错。
同时使用 loaders, options 会报错。
即只有 rule 使用 单一loader 时,才能使用 options。
-
query | object
rule.query 用法和 rule.options 完全一致。
-
rules | [object]
嵌套规则(nested rules)
rule.rules 的用法和 module.rules 的完全一致。
示例:
module: { rules: [{ test: /\.(css|scss)$/, loaders: ['style-loader', 'css-loader'], rules: [{ test: /\.scss$/, loader: 'sass-loader' }] }] }
在上述例子中, .css文件 使用 css-loader、style-loader 处理, .scss文件 会使用 scss-loader、css-loader、style-loader 处理。
注意: 如果 外层规则(rule) 和 嵌套规则(nested rules) 都有 loader,嵌套规则 的 loader 先于 外层规则 的 loader 运行。
-
oneOf | [obj]
规则数组,仅使用 第一个匹配的规则 作用于模块。
示例:
// webpackConfig.js module: { rules: [{ test: /\.css$/, oneOf: [{ resourceQuery: /inline/, loader: 'url-loader' }, { resourceQuery: /external/, loader: 'file-loader' }, { loader: ['style-loader', 'css-loader'] }] }] } // main.js import A from './styles/style.css?inline'
上面的例子中, 模块 A 匹配 oneOf 中的 第一个规则 ,即使用 url-loader 处理源文件,不会再使用 css-loader、style-loader 处理。
注意: 如果 外层规则(rule) 和 oneOf 都有 loader,oneOf 的 loader 先于 外层规则 的 loader 运行。
-
type | string
用于设置 匹配模块的类型,常见的值为:'javascript/auto'、 'javascript/dynamic'、'javascript/esm'、'json'、 'webassembly/experimental'。
构建 parser 会使用这个属性,作用 ???
-
enforce | string
指定 loader 的种类, 可能的值为:"pre" | "post"。
如果 未指定值,则为 normal loader。
在 webpack 中, loader 可分为四类( 按优先级排序): pre loader、inline loader、normal loader、post loader。
rules: [{ test: /\.scss$/, loader: 'sass-loader' }, { test: /\.scss$/, loader: 'css-loader' }, { test: /\.scss$/, loader: 'style-loader' }]
如果未使用 enforce属性 指定 loader 的 优先级,module收集的loaders 将按照 定义顺序倒序执行。 在上面的示例中,对于 .scss 文件, loaders 顺序为 style-loader、css-loader、sass-loader,会导致 编译报错。
rules: [{ test: /\.scss$/, loader: 'sass-loader', enforce: 'pre' }, { test: /\.scss$/, loader: 'css-loader' }, { test: /\.scss$/, loader: 'style-loader', enforce: 'post' }]
使用 enforce属性 后, loaders 顺序为 css-loader、style-loader、sass-loader, 编译成功。
内联loader:
// loader顺序很重要 import css from 'style-loader!css-loader!sass-loader!./styles/style.scss'
所有 normal loader 可以通过在 请求 中加上 ! 前缀来忽略(覆盖)。
所有 normal loader 和 pre loader 可以通过在 请求 中加上 -! 前缀来忽略(覆盖)。
所有 normal loader、pre loader、 post loader 可以通过在 请求 中加上 !! 前缀来忽略(覆盖)。
rules: [{ test: /\.scss$/, loader: 'sass-loader', enforce: 'pre' }, { test: /\.scss$/, loader: 'css-loader' }, { test: /\.scss$/, loader: 'style-loader', enforce: 'post' }] // 不使用css-loader处理 import css from '!./styles/style.scss' // 不使用css-loader、sass-loader处理 import css from '-!./styles/style.scss' // 不使用sass-loader、css-loader、style-loader处理 import css from '!!./styles/style.scss'
-
parser | object
解析器配置项,用于构建解析当前模块的 parser。
???
-
sideEffects
指示模块的哪些部分包含副作用, 详见 tree shaking。
-
resolve | object
可以在 模块级别 配置 解析(resolve), 详见 官网(webpack.js.org/configurati…)。
-
optimization
type: object
webpack4 会根据用户选择的模式 mode 进行优化。我们可以 手动设置optimization 覆盖webpack的默认配置来进行优化。
-
minimize | boolean
告诉 webpack 使用 TerserPlugin 最小化打包文件,对打包文件进行 压缩、混淆。 production模式 下, 默认为 true。
-
minimizer
允许用户提供 一个或多个自定义 的 TerserPlugin实例 去覆盖 默认的TerserPlugin实例。
实际用法详见 官方文档 。
-
splitChunks | object
一个 配置对象,指引 splitChunkPlugin 进行 代码分离。
默认情况下,会将 第三方模块(node_modules)、被至少2个chunk共享的module 分离为新的 chunk。
-
automaticNameDelimiter | string
默认情况下,如果未指定代码分离的 chunk 的 name, webpack会为分离的chunk自动生成 name。
例如, 从 main chunk 分离出 vendors chunk 时, 如果未指定 vendors chunk 的 name, 新生成的 chunk 的名称为 'vendors~main'。
automaticNameDelimiter 属性会指定生成的名称之间的 连接符, 默认为 '~'。
-
automaticNameMaxLength | number
生成的chunk名称字符串的最大长度, 默认为 109。
注意: webpack4 最新版本中,该属性已废弃。
-
chunks | string | function(chunk)
表明可以选择哪些 chunks 中的 modules 进行分离,默认值为 'async'。
代码分离之前,源文件会编译打包成两类 chunk:initial chunk (入口文件所在的chunk) 和 async chunk (懒加载module所在的chunk)。代码分离,就是把一些满足分离条件的 module 从 所在的chunk分离出来,然后重新生成 新的chunk。chunks 会告诉我们分离的时候,module 应该从哪类 chunk 中选择。
如果chunks的值为 'async', 则只能选择 async chunk 中的 module 做代码分离;
如果chunks的值为 'initial', 则只能选择 initial chunk 中的 module 做代码分离;
如果chunks的值为 'all', 可以选择所有的 chunk(async chunk 和 initial chunk) 中的 module 做代码分离;
我们也可以通过自定义一个 function,来筛选chunk进行优化(详见官网)。
-
maxAsyncRequests | number
按需加载 时的 最大允许并行请求数。
production模式 下为 5, development模式 下为 Infinity(不做限制)。
我们通过一个简单的例子来解释:
// webpack.js { mode:'production', entry: { 'main': './src/main.js', }, optimization: { splitChunks: { chunks: 'all' maxAsyncRequests: 1, // 生产模式下, 默认为 5 minSize: 10, cacheGroups: { common: { name: 'common' minChunks: 2, priority: 0 } } } }, ... } // main.js import(/* webpackChunkName: "exp1" */ './examples/example.1.js') import(/* webpackChunkName: "exp2" */ './examples/example.2.js') // example.1.js import { func1 } from '../utils/util.1' export const example1 = () => { func1() console.log('example1') } // example.2.js import { func1 } from '../utils/util.1' export const example2 = () => { func1() console.log('example2') }
第一步,webpack会根据 入口文件main 生成 initial chunk - main chunk;
第二步,从 initial chunk 中分离出 async chunk - exp1 chunk 和 exp2 chunk;
第三步,使用 splitChunkPlugin 将 exp1 chunk 和 exp2 chunk 中的 共享module - func1 分离出来(依据common - cache group)。 这样 main.js 中动态加载 example.1.js的时候,需要加载 common chunk 和 exp1 chunk。
由于 maxAsyncRequests 的 值为 1, 即 按需加载example.1.js 的时候,允许的最大并行请求为 1, 则 代码分离失败,无法将 func1 module 从 exp2 chunk 分离出来。
-
maxInitialRequests | number
入口点处 的 最大并行请求数。
production模式 下为 3, development模式 下为 Infinity(不做限制)。
我们通过一个简单的例子来解释:
// webpack.js { mode:'production', entry: { 'main1': './src/main.1.js', 'main2': './src/main.2.js' }, optimization: { splitChunks: { chunks: 'all' maxInitialRequests: 2, // 生产模式下, 默认为3 minSize: 10, cacheGroups: { vendors: { name: 'vendors', test: /[\\/]node_modules[\\/]/, priority: 10 }, common: { name: 'common' minChunks: 2, priority: 0 } } } }, ... } // main.1.js import Vue from 'vue' import { func1 } from './utils/util.1.js' ... // main.2.js import Vue from 'Vue' import { func1 } from './utils/util.1.js' import { func2 } from './utils/util.2.js' ...
上述例子是一个简单的多页面应用。
第一步, webpack 会将根据 入口文件(main.1.js, main.2.js), 生成两个 initial chunk(main.1 - [vue module, func1 module],main.2 - [vue module, func1 module, func2 module]);
第二步,使用 splitChunkPlugin插件 进行代码分离, 先将 vue module(满足vendors - cacheGroup) 分离到 vendors chunk, 然后将 func1 module(满足common - cacheGroup) 分离到 common chunk。分离完成以后,加载 main.1 chunk 之前需要先加载 vendors chunk、 common chunk, 这样加载首页的时候就会有 vendors、common、main.1 三个请求。
由于 maxInitialRequests 的值为 2, 即入口处的并行最大请求数为2, 因此 func1 module 从 main.1 chunk 中分离的时候, 由于已经有 vendors、main.1 两个chunk, 代码分离失败, 不能分离为 新的chunk。
-
minChunks | number
代码分割前必须共享模块的最小块数。即如果minChunks为3, 则 module 必须被至少三个chunk共享才能被分离出来, 默认值为 1。
注意: 如果分离出来的chunk的大小小于 minSize,则 代码分离不起作用。
-
minSize | number
指定生成块的最小大小, 以字节为单位。
production模式 下默认为 30000字节。
development模式 下默认为 10000字节。
如果分离出来的 chunk 的大小小于 minSize, 则 代码分离不起作用。
注意:代码分离的时候如果满足 minChunks、maxInitialRequests、maxInitialRequests、 cacheGroup(enforce: false) 但是不满足 minSize, 代码分离还是会失效。
-
maxSize | number
webpack尝试将大于 maxSize 的块拆分成更小的部分。
一般我们会把第三方库单独打包成一个chunk: vendors。如果第三方库比较大,导致vendors会比较大,导致更大的下载量。 此时,我们可以通过设置 maxSize 属性, 将 vendors chunk 拆成更小的 chunk。
-
name | string | boolean | function: string
指定 代码分离 以后生成的 新的chunk 的名称,默认值为 true。
如果 name的值为 true,使用 cacheGroup的属性名、源chunk的名称 来生成 chunk 的名称 如 'vendors~chunk';
如果 name 的值为 false 则使用 chunk 的 index 作为 chunk 的名称,名称为 数字;
如果 name 的值为 字符串,会使用当前字符串作为 chunk 的名称;
如果 name 的值为 函数, 使用 函数 的 返回字符串作为 chunk的 名称;
如果将name的属性设置为字符串或者返回字符串的函数,源chunk分离出来的多个chunk会合并为一个chunk,可能会导致更大的初始下载量和减慢页面的加载速度。
一般情况下,name属性更多的使用在 cacheGroup中,详见 官方文档。
-
cacheGroups
缓存组,用于指定 代码分离策略,将满足条件的 module 从原来所属的 chunk(initial chunk / async chunk) 中分离出来, 构成新的 chunk。cacheGroup 可以 继承/复写splitChunks的任何配置,只有 test、priority、 reuseExistingChunk 是 cacheGroups 特有的。
cacheGroups的默认值如下:
{ ... optimization: { splitChunks: { cacheGroups: { // 将被至少2个chunk共享的module分离成新的chunk default: { automaticNamePrefix: '', reuseExistingChunk: true, minChunks: 2, priority: -20 }, // 将引用的第三方库分离成新的chunk vendors: { automaticNamePrefix: 'vendors', test: /[\\/]node_modules[\\/]/, priority: -10 } } } } }
-
priority | number
指定 cache group 的 优先级。
如果一个模块可以属于多个 cache group, 那么它将属于 优先级更高 的 cache group。 例如,一个第三方模块(jquery),既满足 'vendors' 条件, 也满足 'default' 条件,但是由于 'vendors' 的优先级高于 'default', jquery 模块最后会被分离到 vendors chunk 中。
默认 cache group 的优先级为 负数(vendors: -10, default: -20), 我们可以自定义 cache group, 只要 priority 的值大于-10, 即可先于默认cache group 发挥作用。
-
reuseExistingChunk | boolean
如果分离出来的module已经存在于某个chunk中,那么重用这个chunk,不需要重新生成一个chunk。 这样可能导致生成的chunk的名称不符合预期。
我们通过一个简单的例子来说明:
// webpack { splitChunks: { cacheGroups: { common: { name: 'common', minChunks: 2, priority: 0, reuseExistingChunk: false, enforce: true } } } } // main.1.js import(/* webpackChunkName: "exp1" */ './examples/example.1.js') import(/* webpackChunkName: "exp2" */ './examples/example.2.js') // example.1.js import { func2 } from '../utils/util.2' export const example1 = () => { func2() console.log('example1') } // example.2.js import { func2 } from '../utils/util.2' export const example2 = () => { func2() console.log('example2') } // main.2.js import(/* webpackChunkName: "util1" */ './utils/util.1') import(/* webpackChunkName: "util2" */ './utils/util.2') // util.1.js export const func1 = () => { console.log('func1') } // util.2.js export const func2 = () => { console.log('func2') }
上面的例子是一个简单的多页面应用。
第一步, webpack 会将根据 入口文件(main.1.js, main.2.js), 生成两个 initial chunk(main.1 chunk, main.2 chunk) 和 四个 async chunk(exp1 chunk, exp2 chunk, util1 chunk, util2 chunk);
第二步,使用 splitChunkPlugin插件 进行 代码分离。由于 util.2 module 被 exp1 chunk, exp2 chunk,util2 chunk 共享, 将会被分离成一个 新的chunk:'common'。
如果 reuseExistingChunk 的值为 true,由于 common chunk 中的 module 在 util2 chunk 中存在, 所以 util2 chunk 会被复用, common chunk 不会被新建, 最后输出的 chunk 为: main.1, main.2, exp1, exp2, util1, util2。
如果 reuseExistingChunk 的值为 false,common chunk 会被创建, 最后输出的 chunk 为: main.1, main.2, exp1, exp2, util1, common(exp1、exp2、util2 中的 util.2 module 会分离到 common chunk 中, 导致 util2 chunk 中的 module 为 0, 然后被删除)。
-
test | string | Regexp | function(module, chunks): boolean
选择满足条件的module来生成chunk,详见 官方文档。。
-
filename | string
和 output.filename 用法一样。当且仅当是 initial chunk 时,覆盖文件名。(待研究)
-
enforce | boolean
如果为 true,则始终为当前 cache group 创建 chunk,默认为 false。
splitChunks: { minSize: 30000, cacheGroups: { common: { name: 'chunk-common', minChunks: 2, enforce: true } } }
webpack 会根据上面的配置项将 被至少2个chunk共享的module 分离为 新的chunk('chunk-common',实际大小为10kb)。如果 enforce 为 false, 由于 chunk-common的实际大小小于minSize(30kb), 代码分离失效,chunk-common块不会生成。此时,我们可以将 enforce 设置为 true,强制令代码分离生效, 生成 chunk-common。
-
-
-
runtimeChunk | boolean | object
webpack 编译打包源文件时,会生成一段 runtime代码, 用于 加载chunk 、加载module、缓存module等。如果 runtimeChunk 配置项的值为 true 或者 object 时, runtime代码 会从被分离成一个单独的 chunk(runTime chunk)。应用加载时, runtime chunk 会首先加载。
默认情况下为 false,即不分离 runtime chunk。如果 runtimeChunk 的值为对象,对象只有一个name属性,用于声明 runtime chunk 的名称。
optimization: { runTimeChunk: true // 生成名称为 runtime~main.js 的chunk } // 如果配置项的值为对象, 对象的属性只有name。 name的类型可以为字符串或者函数 optimization: { runTimeChunk:{ name: 'runtime' // 生成名称为 runtime.js 的chunk } } optimization: { runTimeChunk:{ name: function(entrypoint) { // entrypoint -> entry chunk, 一般为main chunk return `runtime~${entrypoint.name}` // entrypoint.name => main } } }
-
noEmitOnErrors | boolean
编译错误时,emit阶段会跳过,即不会输出打包文件到指定位置。production模式 下,默认为 true。
-
namedModules | boolean
在编译过程中,每一个 module 都会生成一个 标识符 用于标识 module。如果设置为true,在打包文件中会以 模块源文件的路径 作为标识符, 方便我们调试。
optimization.namedModules: true 等同于 optimization.moduleIds: 'named'
development模式 下, 默认为 true; production模式 下,默认为 false。
// main~chunk.js (window["webpackJsonp"] = window["webpackJsonp"] || []).push([[2],{ /***/ "./src/main.js": // 以'.src/main.js' 标识 main.js 对应的 module /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/_vue@2.6.10@vue/dist/vue.runtime.esm.js"); console.log(vue__WEBPACK_IMPORTED_MODULE_0__[/* default */ "a"]) alert('1') /***/ }) },[["./src/main.js",0,1]]]);
-
namedChunks | boolean
如果设置为 true,在打包文件中使用 chunk的名称 来标识 chunk,方便我们调试。
optimization.namedChunks: true 等同于 optimization.chunkIds: named。
development模式 下,默认为 true,production模式 下,默认为 false。
// main~chunk.js // namedChunks: false, 以数字作为chunk的标识符; (window["webpackJsonp"] = window["webpackJsonp"] || []).push([["2"],{ ... },[["Vtdi","0","1"]]]); // namedChunks: true, 以chunk的名称作为chunk的标识符 (window["webpackJsonp"] = window["webpackJsonp"] || []).push([["main"],{ ... },[["Vtdi","runtime~main","chunk-vendors"]]]);
-
modulesId | boolean | string
告诉webpack使用哪种算法来生成 module id。 在最后的打包文件中,会使用 module id 来标识每一个 module。
值 说明 false 使用内置的算法生成 module id, module id 为 数字 natural 使用 module 在 modules列表 中的 index 作为 id,main.js 对应的 module id 为 0 named 使用 源文件url 作为 module id hashed 使用 源文件url 通过 md5算法 生成的 hash值 的 前四位 作为 module id size 将 modules 按照 最小的初始下载大小排序, module 的 index 即为 module id(未理解) total-size 将 modules 按照 最小的总下载大小排序, module 的 index 即为 module id(未理解) moduleIds: 'hash' 比较常用。
-
chunkIds
告诉 webpack 使用那种算法来生成 chunk id。 在最后的打包文件中,会使用 chunk id 来标识 chunk。
值 说明 false 将 chunks列表 中的 chunk 按照 name 从小到大排序, chunks列表 中 chunk的index 即为 chunk id natural 将 chunks列表 中的 chunk 按照 加载顺序 从小到大排序, chunks列表 中 chunk的index 即为 chunk id named 将 chunk 的名称作为 chunk id,方便调试 size 将 chunks 按照 最小的初始下载大小排序, chunk 的 index 即为 chunk id(未理解) total-size 将 chunks 按照 最小的总下载大小排序, chunk 的 index 即为 chunk id(未理解) -
removeAvailableModules | boolean
如果 children chunk 中含有 parent chunk 已经存在的 module,将 module 从 children chunk 中移除。
我们通过一个简单的例子来说明:
// main.js import { func1 } from './utils/util.1' func1() import(/* webpackChunkName: "example1" */ './examples/example.1.js').then(res => { res.example1() }) // example1.js import { func1 } from '../utils/util.1' export const example1 = () => { func2() console.log('example1') }
我们在使用 webpack 编译打包源文件的时候,会先将源文件打包为一个 initial chunk(main)。如果有需要 动态导入 的 module,则会创建一个 新的chunk,即 async chunk(example1)。此时 main chunk 为 example1 chunk 的 parent。
如果 removeAvailableModules 为 true, webpack 会检查 example1 chunk 中包含的 module(util.1) 是否也存在于 main chunk 中, 如果存在,删除 example1 chunk 中的对应 module,即 example1打包文件 中不包含 utils.1 模块。
如果将 removeAvailableModules 属性设置为false,webpack 将不会检查 子chunk 中是否存在 重复module 并移除, 即 'main'打包文件 和 'example1'打包文件 中都含有 utils.1 模块。
不管是 production模式 还是 development模式,removeAvailableModules 默认为 true。
-
nodeEnv | string
告诉 webpack 将 process.env.NODE_ENV 设置为给定的 字符串值(production / development)。
默认为 mode配置项 的值, 如果未指定 mode 的值,设置为 'production'。
-
mangleWasmImports
默认值为 false。
-
removeEmptyChunks | boolean
默认为 true,如果生成的 chunk 中没有 module,则将 chunk 移除。
在使用 spiltChunkPlugin 做 代码分离 的时候,可能会出现 收集的module被分离为新的chunk而导致自己的modules列表为空 的情况。此时, 没有module的chunk就会被移除。
-
mergeDuplicateChunks | boolean
默认为 true,告诉 webpack 合并包含相同 modules 的 chunk。
mergeDuplicateChunks 配置项会指引 MergeDuplicateChunksPlugin 对 源文件编译打包以后的chunks 做优化,将 包含相同modules 的 chunks 做合并处理。优化以后的 chunks 才会使用 splitChunkPlugin 做 代码分离。
我们通过一个简单的小例子来说明一下:
// webpack.js { entry: { 'main1': './src/main.1.js', 'main2': './src/main.2.js' }, optimization: { mergeDuplicateChunks: true } } // main.1.js import(/* webpackChunkName: "exp1" */ './examples/example.1.js') // main.2.js import(/* webpackChunkName: "example1" */ './examples/example.1.js')
源文件会通过 webpack 打包成两类 chunk: initial chunk(main.1 chunk, main.2 chunk), async chunk(exp1 chunk,example1 chunk);
如果 mergeDuplicateChunks 的值为 true, 对生成的 chunks 优化。上述 chunks 中, exp1 chunk 和 example chunk 中的 module 完全一致, example chunk 会合并到 exp1 chunk 中。合并完成以后,example1 chunk 会被 删除。 这样使用 splitChunkPlugin 进行 代码分离 的 chunks 为: main.1 chunk、main.2 chunk、exp1 chunk。
如果 mergeDuplicateChunks 的值为 false, 则 不作合并优化,使用 splitChunkPlugin 进行 代码分离 的 chunks 为: main.1 chunk、main.2 chunk、exp1 chunk、 example1 chunk。
-
flagIncludedChunks | boolean
production模式 下,默认为 true。
假设存在两个 chunkA(id = 'A'), chunkB(id = 'B')。如果 chunkA 是 chunkB 的 子集(即chunkA中的module在chunkB中都存在), 那么 chunkB 的 id = 'B,A'。
我们通过一个简单的小例子来说明:
// main.js import(/* webpackChunkName: "exp1" */ './examples/example.1.js') import(/* webpackChunkName: "exp2" */ './examples/example.2.js') // example.1.js import { example3 } from './example.3.js' export const example1 = () => { example3() console.log('example1') } // example.2.js export const example2 = () => { import(/* webpackChunkName: "exp3" */ './examples/example.3.js') console.log('example2') } // example.3.js export const example3 = () => { console.log('example3') }
上面的例子中,会生成三个 async chunk:exp1 chunk、 exp2 chunk、 exp3 chunk。由于 exp3 chunk 中的 modules 在 exp1 chunk 中都存在, 所以 exp3 chunk 为 exp1 chunk 的子集, exp1 chunk 的 id 为 'exp1, exp3'。
应用启动的时候, 会通过 动态添加script的方式 加载 exp1 chunk、exp2 chunk。由于 exp1 chunk 的 id 为 'exp1, exp3', 所以会认为 exp1、exp2、exp3 都已经加载了。 这样当我们需要加载 exp3 chunk 的时候,就不要通过动态添加script的方式来加载了,直接使用 缓存 即可。
-
occurrenceOrder | boolean
告诉 webpack 找出 module 的顺序,导致最小的初始包。
optimization.occurrenceOrder: true 等同于 optimization.chunkIds: 'total-size'。
optimization.occurrenceOrder: true 也等同于 optimization.moduleIds: 'size'。
production模式 下默认为 true。
-
providedExports | boolean
默认为 true。 告诉 webpack 找出 module 的 输出 来生成更有效的代码。
我们通过一个简单的例子来说明:
// main.js import { add, sub } from '../utils/util.js' add() sub() // util.js export const add = () => { console.log('add') } export const sub = () => { console.log('sub') }
启动应用后,我们会加载 main module、 util module, 然后缓存到 installedModules 中, installedModules 的结构为:
installedModules = { 'main.js': { i: 'main.js', // module id l: true, // module 是否已加载 exports: {} // module 输出 }, 'util.js': { i: 'util.js', l: true, exports: { add: function() {...}, sub: function() {...} } } }
如果 providedExports 的值为 true, 则会对 util module 的输出的名称进行 优化, 即 installedModules['util.js'].exports = {a: function(...) {}, b: function() {...}};
如果 providedExports 的值为 false, installedModules['util.js'].exports = {add: function(...) {}, sub: function() {...}};
-
usedExports | boolean
production模式 下为 true。告诉 webpack 确定每个 module 已使用的导出, 为 使用的导出 生成 导出。
我们通过一个简单的例子来说明:
// main.js import { add, sub } from '../utils/util.js' add() // util.js export const add = () => { console.log('add') } export const sub = () => { console.log('sub') }
启动应用后,我们会加载 main module、 util module, 然后缓存到 installedModules 中, installedModules 的结构为:
installedModules = { 'main.js': { i: 'main.js', // module id l: true, // module 是否已加载 exports: {} // module 输出 }, 'util.js': { i: 'util.js', l: true, exports: { add: function() {...}, sub: function() {...} } } }
在上面的示例中, util module 的输出,只有 add 被用到。
如果 usedExport 为 true, 那么 installedModules['util.js'].exports = { add: function() {...}};
如果 usedExport 为 false, 那么 util module 的 所有输出 还是会出现中 exports 中。
注意:如果 usedExport 为 true, sub 方法不会出现在 exports 中。 sub方法代码 尽管没有使用, 但还是会被打包。 使用 tree shaking 才能在打包过程中去除 未使用的代码。
-
concatenateModules | boolean
连接多个module为一个module。
production模式 下默认为 true。
示例:
// main.js import { add } from './utils/util.1.js' // util.1.js export const add = () => { console.log('add') }
如果 concatenateModules 为true, util.1 module 和 main module 会合并为一个 module;
如果 concatenateModules 为 false, 不做 合并。
ES6模块才可以被合并。模块合并 发生在 代码分离 之后。
-
sideEffects | boolean
用于移除 JavaScript上下文 中的 未引用代码(dead-code) - tree shaking。
product模式 下默认为 true。
为了 tree shaking 生效, 我们需要:
-
使用 ES2015 模块语法(即 import 和 export);
-
在项目 package.json 文件中,添加一个 "sideEffects" 入口。
详细用法见: 官方文档。
-
-
portableRecords | boolean
告诉 webpack 生成 具有相对路径的记录,以便能够 移动上下文文件夹。
默认情况下,optimize.portableRecords 被禁用。
如果至少有一个记录选项( recordsPath,recordsInputPath,recordsOutputPath)提供,则自动启用。
output
type: Obect
用于指示 webpack 如何以及在何处输出打包文件、资源以及其他使用webpack打包或者加载的文件。
-
path | string
指定 打包文件 的 输出目录,即打包后 文件在硬盘中的存储位置。
输出目录是一个 绝对路径。
-
publicPath | string
此选项指定在浏览器中所引用的 输出目录(path)对应的公开URL。
publicPath 并不会对 生成文件的路径 造成影响,主要是 对页面里面引入的资源的路径做对应的补全。
{ output: { path: path.resolve(__dirname, '../dist'), // 打包文件会输出到path指定的位置 publicPath: '/' // 浏览器会访问 publicPath 指定位置的文件 } }
-
pathinfo | boolean
告诉 webpack 在 chunk 中引入 所包含模块信息的相关注释。
默认值 是 false,并且 不应该用于生产环境(production),但是 对阅读开发环境(development)中的生成代码(generated code)极其有用。
这些注释也会被添加至经过 tree shaking 后生成的 bundle 中。
-
filename | string | function
指定 输出的打包文件 的 文件名, 默认值为 空。
我们可以使用以下常用方式为每一个 打包文件 提供 唯一 的 文件名:
-
'bundle.js' - 指定 入口文件(main.js) 所在的 chunk 的 文件名, 仅适用于单页面应用;
-
'[name].js' - 使用 chunk 的 name;
-
'[name].[hash].js' - 使用 compilation 的 hash,所有chunk文件名中hash值一样;
-
'[name].[chunkhash].js' - 使用 chunk 内容的 hash,每个chunk文件名中的hash值都不一样;
-
'[name].[id].js' - 使用 chunk 的 id;
-
[name].[contenthash].js - 使用提取内容的 hash,一般应用于将 css 提取为单独的文件。
我们也可以将 filename 指定一个 function 来返回输出的文件名, 返回值 的格式和上面一样。
常用命名方式: [name].[chunkhash].js
-
-
chunkFilename | string
指定 非入口chunk(不包含runtime code) 的文件名。
如果未指定, 使用 '[id].js' 或者 filename指定的文件名。
-
chunkLoadTimeout | number
chunk请求超时的时间,单位为 毫秒,默认为 120000。
我们会通过 动态添加script元素 的方式来进行 懒加载。如果在指定时间内未获取到指定的chunk, 则认为 超时。
-
crossOriginLoading | boolean | string
告诉 webpack 是否启用 chunk 的 跨域加载, 默认值为 false。
如果值为 false, 禁用;如果值为 字符串,在 动态添加script元素 的方式来进行 懒加载时,会给 script元素 添加 crossorigin 属性。
'anonymous' - 无需凭据 即可启用 跨域加载;
'use-credentials' - 使用凭证 启用 跨域加载';
-
jsonpScriptType | string
在 动态添加script元素 的方式来进行 懒加载时,指定 script元素 的类型,即 设置type属性的值。
如: jsonpScriptType: 'text/javascript'
-
library | string | object
常用于 开发类库, 需和 libraryTarget属性 配合使用。
如果是 string,将 入口文件的返回值 赋值给 library属性 指定的 变量。
如果是 object, 则用于给每个 target(libraryTarget) 起不同的名称。
output: { library: { root: "MyLibrary", amd: "my-library", commonjs: "my-common-library" }, libraryTarget: "umd" }
-
libraryTarget | string
配置如何暴露 library。 假设 output.library: 'myLibrary':
-
'var'
类库加载完毕以后,入口文件的返回值 将分配给一个 使用var定义的变量。
// 编译打包以后的输出文件: main.js var myLibrary = (function(modules){ return xxx })([...modules])
-
'assign'
类库加载完毕以后,入口文件的返回值 将分配个一个 不使用var定义的变量。
// 编译打包以后的输出文件: main.js myLibrary = (function(modules){ return xxx })([...modules])
-
'this'
类库加载完毕以后,入口文件的返回值 将作为 当前上下文this 的一个 属性,属性名为 myLibrary。
// 编译打包以后的输出文件: main.js // this 一般为 window this["myLibrary"] = (function(modules){ return xxx })([...modules])
-
'window'
类库加载完毕以后,入口文件的返回值 将作为 window对象 的一个 属性,属性名为 myLibrary。
// 编译打包以后的输出文件: main.js window["myLibrary"] = (function(modules){ return xxx })([...modules])
-
'self'
类库加载完毕以后,入口文件的返回值 将作为 self 的一个 属性,属性名为 myLibrary。
// 编译打包以后的输出文件: main.js self["myLibrary"] = (function(modules){ return xxx })([...modules])
-
'global'
类库加载完毕以后,入口文件的返回值 将作为 globalObject属性指定的全局变量 的一个 属性,属性名为 myLibrary。
// 编译打包以后的输出文件: main.js // globalObject 默认为 window window["myLibrary"] = (function(modules){ ... })([...modules])
-
'commonjs'
输出的类库符合 commonJs规范。
入口文件的返回值 将作为 exports 的一个 属性,属性名为 myLibrary。
// 编译打包以后的文件: main.js exports["myLibrary"] = (function(modules){ return xxx })([...modules])
-
commonjs2
输出的类库符合 commonJs规范。
入口文件的返回值 会被分配给 module.exports。
// 编译打包以后的文件: main.js module.exports = (function(modules){ return xxx })([...modules])
-
amd
输出的类库 符合 AMD规范。
// 编译打包以后的文件: main.js define("MyLibrary", [], function() { return (function(modules){ return xxx })([...modules])}
-
umd
输出的类库 符合 UMD规范。
// 编译打包以后的输出文件:main.js (function(root, factory){ if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["my-common-library"] = factory(); else root["MyLibrary"] = factory(); }(window, function() { return (function(modules){ ... })([...modules]) }))
-
jsonp
将 入口起点 的 返回值,包裹到一个 jsonp 包装容器中。
MyLibrary((function(modules){ return xxx })([...modules]))
需配合 extenals配置项 使用。
-
system
输出类库格式:
System.register("MyLibrary", [], function(__WEBPACK_DYNAMIC_EXPORT__) { return { execute: function() { __WEBPACK_DYNAMIC_EXPORT__((function(modules) { return xxx }([...modules]))); } }; });
系统模块 要求在执行 类库时,需要 浏览器 中存在 全局变量System。
-
-
globalObject | string
和 library、libraryTarget 一起使用,指示将 入口文件的返回值 分配给哪个 全局对象。
默认值为 window。
// webpack.js output: { library: 'myLibrary', libraryTarget: 'global', globalObject: 'self' } // 编译打包以后的文件: main.js self["myLibrary"] = (function(modules){ return xxx })([...modules])
-
libraryExport | string | [string]
用于指定 具体的入口文件的返回值。
常见的使用方式:
- 未指定值
// webpack.js outout: { library: 'myLibrary', libraryTarget: 'var' } // main.js var myLibrary = (function(modules){ return xxx })([...modules])
- 'default'
// webpack.js outout: { library: 'myLibrary', libraryTarget: 'commonjs2', libraryExport: 'default' } // main.js module.exports = (function(modules){ return xxx })([...modules])["default"]
- 'myModule'
// webpack.js outout: { library: 'myLibrary', libraryTarget: 'amd', libraryExport: 'myModule' } // main.js define("MyLibrary", [], function() { return (function(modules){ return xxx })([...modules])["myModule"]})
- ['myModule', 'mySubModule']
// webpack.js outout: { library: 'myLibrary', libraryTarget: 'umd', libraryExport: ['myModule', 'mySubModule' } // main.js (function(root, factory){ if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["my-common-library"] = factory(); else root["MyLibrary"] = factory(); }(window, function() { return (function(modules){ return xxx })([...modules])["myModule"]["mySubModule"] }))
-
auxiliaryComment | string | object
在和 output.library 和 output.libraryTarget 一起使用时,此选项允许用户向 导出容器(export wrapper) 中插入 注释。
具体用法详见: 官网。
-
jsonpFunction | string
当 输出多个chunk 时, webpack 会构建一个 全局方法, 用于 安装chunk。
jsonpFunction 可用于指定 安装chunk 的 方法名。
如果 未指定, 则方法名为:'webpackJsonp'。
如果 指定(如:'myFunction'), 则方法名为 'myFunction'。
// 未指定 (window["webpackJsonp"] = window["webpackJsonp"] || []).push([[0],[...modules]) // jsonpFunction: 'myFunction' (window["myFunction"] = window["myFunction"] || []).push([[0],[...modules])
-
sourceMapFilename
配置 source map 的命名方式。默认使用 '[file].map'。
只在 devtool 启用了 SourceMap 选项时才使用。
-
strictModuleExceptionHandling | boolean
如果一个模块在导入时抛出异常,告诉 webpack 从 模块实例缓存 中 删除 这个模块。
默认值为 false, 即 不删除。
如果设置为 true, 删除。
// strictModuleExceptionHandling: true function __webpack_require__(moduleId) { // Check if module is in cache if(installedModules[moduleId]) { return installedModules[moduleId].exports; } // Create a new module (and put it into the cache) var module = installedModules[moduleId] = { i: moduleId, l: false, exports: {} }; // Execute the module function var threw = true; try { // 导入模块 modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); threw = false; } finally { // 导入模块时, 如果发生异常,将模块实例从installedModules缓存中删除 if(threw) delete installedModules[moduleId]; } // Flag the module as loaded module.l = true; // Return the exports of the module return module.exports; } // strictModuleExceptionHandling: false function __webpack_require__(moduleId) { // Check if module is in cache if(installedModules[moduleId]) { return installedModules[moduleId].exports; } // Create a new module (and put it into the cache) var module = installedModules[moduleId] = { i: moduleId, l: false, exports: {} }; // Execute the module function modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); // Flag the module as loaded module.l = true; // Return the exports of the module return module.exports; }
-
umdNamedDefine| boolean
会对 UMD 的构建过程中的 AMD 模块进行命名。否则就使用 匿名 的 define。
// webpack.js output: { libraryTarget: 'umd', umdNamedDefine: true, library: 'myLibrary' } // main.js (function(root, factory){ if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) // 如果 umdNamedDefine: false, 则define([], factory) define(["myLibrary"], factory); else if(typeof exports === 'object') exports["myLibrary"] = factory(); else root["MyLibrary"] = factory(); }(window, function() { return (function(modules){ ... })([...modules]) }))
-
futureEmitAssets | boolean
告诉 webpack 在 输出文件到指定位置 时,使用 未来的版本, 它允许输出以后 释放内存。
在 webpack5 中 移除,作为一个 默认行为。
output剩余配置项使用较少, 后续整理。
devtool
type: string | boolean
该配置项用以控制是 否生成source map 以及 怎样生成source map。
不同的值会明显影响到 构建(build) 和 重新构建(rebuild) 的速度。
source map 是一个 信息文件,里面储存着 位置信息。也就是说,转换后的代码 的每一个位置,所对应的 转换前的位置。 source map 文件的 内容结构 如下:
{
// source map 的版本
"version": 3,
// 转换前的文件名, 是一个数组, 可能存在文件合并
"sources": ["webpack:///./src/examples/example.1.js"],
// 转换前的所有变量名和属性名
"names": ["a", "example1", "alert"],
// 记录位置信息的字符串(一个 ; 代表一个行映射, 一个 , 代表一个列映射)
"mappings": ";;;;;;AAAA;AAAA;AAAA,IAAMA,IAAI,KAAV;AACO,IAAMC,WAAW,SAAXA,QAAW,GAAM;AAC1BC,UAAMF,CAAN;AACH,CAFM,C",
// 转换后的文件名
"file": "exp1.js",
// 转换前的内容
"sourcesContent": ["const a = '123'\r\nexport const example1 = () => {\r\n alert(a)\r\n} "],
// 转换前的文件所在的目录。如果与转换前的文件在同一目录,该项为空
"sourceRoot": ""
}
devtool 的各个配置项,其实是由几个 关键字: eval, source-map, cheap, module, inline, hidden, nosources 组合生成的。这几个关键字的含义如下:
-
eval
使用 eval() 包裹模块代码。
-
source-map
生成 .map 文件,在 调试 时用于 追踪转换前的代码。
-
cheap
需配合 'source-map' 一起使用, Source Map 中只有 生成的代码(generated code) 和 转换后的代码(transformed code) 之间的 行映射关系, 没有 列映射关系。
-
module
需配合 'source-map' 一起使用,Source map 中存在 生成的代码(generated code) 和 源代码(riginal source) 之前的 行映射 关系、列映射 关系。
-
inline
需配合 'source-map' 一起使用,不单独生成 .map 文件,.map 文件作为 DataUrl 嵌入 **打包文件(bundle)**中。
-
hidden
需配合 'source-map' 一起使用,会生成 .map文件,但 不会为 bundle 添加引用注释。
-
nosources
需配合 'source-map' 一起使用,会生成 .map文件,但是 sourcesContent 的内容为空,无法追踪转换以后的代码或者源代码。
具体用法详见: 官网。
devServer
type: object
我们通过使用 webpack-dev-server 来快速开发应用程序。
devServer配置项 用于指引 wepack-dev-server 的行为。
当我们通过 Node.js API 来使用 dev-server, devServer 中的选项将被忽略。将选项作为第二个参数传入: new WebpackDevServer(compiler, devServer)。
-
inline | boolean
development模式 下,webpack-dev-server 会 监听源文件是否发生变化。 如果发生变化,会 自动刷新页面。
默认值为 true, 即为 inline模式。 如果 inline 的值为 false, 则为 iframe模式。
inline模式 和 iframe模式 的原理相同, 都是 浏览器 和 服务器 之间建立 websocket连接。当源文件发生变化时,通知浏览器 重新加载页面 进行更新。
inline模式 下, 浏览器端 建立websocket连接的逻辑代码 会和我们的 应用代码 打包到一起, 会增加编译时间;
iframe模式 下,浏览器端 建立websocket连接的逻辑代码 和 我们的应用代码 是分开的。 当我们通过 localhost:port/webpack-dev-server/ 访问应用时, 服务端会返回一个 html页面。html页面 中会包含一个 live.bundle.js 的文件, 负责 建立与服务器之间的websocket连接, 并 动态建立一个iframe用于加载实际应用。当源文件发生变化时, 页面不刷新, 会通知 iframe 重新更新。
iframe模式 下无法启用 HMR。
-
hot | boolean
设置为 true,将启用 HMR 功能。
若想触发 HRM 功能,需满足三个条件:
-
hot配置项 的值为 true;
-
启用 inline模式;
-
必须显示声明 module.hot.accept('url', callback), 否则只能刷新页面;
-
-
hotOnly | false
默认情况为 false,当 HMR 失败以后,浏览器端通过 重新加载页面 来 响应服务端更新。
如果设置为 true, 当 HMR 失败以后, 浏览器端无法响应服务端更新。
如果未显示声明 module.hot.accept('url', callback), HMR 就会失败, 若此时 hotOnly 的值为 true, 则 浏览器端无法响应服务端更新。
-
open | boolean
设置为true, dev-server 自动打开 默认浏览器 启动应用。
-
useLocalIp
设置为true,dev server 会以 本地IP 打开默认浏览器。
使用时,open = true。
-
openPage | string
指定 dev-server 自动打开 默认浏览器 以后的 默认跳转页面。
-
host | string
指定要使用的 host, 默认是 localhost。
-
port | string
指定监听的 端口号, 默认是 8080。
-
liveReload
默认情况下,dev-server 将在 检测到参与编译打包的文件文件更改 时 重新加载/刷新页面。 即如果如果一个文件 未参与编译打包过程, 那么它发生变化时 不会触发重新加载/刷新页面。
通过将 liveReload 设置为 false 来 禁用 它(修改什么文件也 不会触发重新加载/刷新页面)。
-
contentBase | boolean | string | [string] | number
告诉服务器从哪里提供内容,默认值为 当前工作目录。
-
watchContentBase
告诉 dev-server 监视 devServer.contentBase选项 所服务的文件, 默认情况下 禁用 它。
默认情况下, 如果一个文件 参与编译打包过程,那么当这个文件发生变化时,才会 触发重新加载/刷新页面, 否则 无效。
设置为 true 后 启用,即使某个文件 未参与编译打包,当它发生变化时,也会 触发重新加载/刷新页面。
-
watchOptions | object
一个配置项集合,用于自定义 watch mode。
-
aggregateTimeout | number
在 第一个文件 修改以后,延迟重新编译 的过程。这允许 webpack 将在这个时间段内的所有修改 聚合 到一个重新编译的过程中。
传递的值以 毫秒 为单位。
-
ignored | RegExp
不监听 满足 ignored 条件的文件的变化。
-
poll | boolean | number
通过传递 true 或者 以毫秒为单位的数值指定轮询间隔 来 启用轮询,检查文件变化。
当 文件监听不起作用 时,可以尝试启用 poll 功能。
-
-
writeToDisk | boolean | function:filePath
默认为 false, 即 不将编译打包以后的内容写入磁盘。
如果设置为 true,会将 编译打包以后的内容 写入 output配置项 指定的位置。
如果设置为 function,该 function 是一个 filter function, 将 满足条件的文件名对应的文件写入磁盘。
具体用法详见 官网文档。
-
lazy | boolean
如果设置为 true, dev-server会进入 懒惰模式, 仅在请求时编译该bundle。 这意味着 webpack不会监视任何文件更改。
???
注意:使用 lazy模式 时, 必须提供 filename, 否则报错。
-
filename | string
此选项可让您减少 lazy模式 下的 编译。 默认情况下,在 lazy模式 下,每个请求都会产生 新的编译。 使用 filename,只能在请求某个文件时进行编译。
???
-
overlay | boolean | object
当存在 编译错误或者警告 时,将 错误或者警告 以 全屏覆盖 的形式在浏览器中展示。
默认 禁用, 具体用法详见 官网文档 。
-
proxy | object | [object, function]
在 前后端分离 的开发过程中,使用 proxy 可以有效的帮我们解决 跨域请求问题。
通常,我们会在 proxy配置项 中指定每个 API请求 对应的 代理。
{ devServer: { proxy: { 'test': { target: 'http://localhost:3000', changeOrigin: true, router: {...} }, } } }
-
target | string
指定一个 服务器地址。
dev-server 接收到一个 API Request 以后,会向 匹配的test 对应的 服务器 重新发出 Request, 将 response 通过 dev-server 返回给 Client。
-
changeOrigin | boolean
默认值为 false。
如果指定为 true,??
-
pathRewrite | object | function
重写 Request API。
如果 pathRewrite 的值为 object, 则 key 为一个 RegExp,value 为 string, Request API 中 匹配RegExp 的会被 string 替换;
如果 pathRewrite 的值为 function, 可自定义返回新的 Request API。
-
router | object | function
如果请求的 host 或者 host + path 能匹配 router 配置项中的属性 key,则使用对应的属性值 value 覆盖 proxy.target。
其他配置项及详细用法详见: http-proxy-middle
-
-
progress | boolean
在 控制台 输出 进度信息,仅适用于 CLI模式。
-
allowedHosts | array
将允许访问 dev server 的 服务列入白名单。
剩余配置项应使用较少,后续整理。
target
type: string | function(compiler)
webpack 能够为 多种环境 编译构建, 可通过 target配置项 指定一个 具体的环境。
如果 target 的值为 字符串, 可以支持以下环境:
-
web
webpack编译打包的代码 应用于 web环境(浏览器)。对于需要 懒加载的chunk,会通过 动态添加script元素的方式加载,然后通过一个 全局方法(webpackJsonp) 来安装。
-
webworker
webpack编译打包以后的代码 应用于 web worker环境。使用 chunk 时,通过 importScripts 方法加载。
// chunk.js self["webpackChunk"]([0],{ 5: (function(module, __webpack_exports__, __webpack_require__) { ... }) }); // 加载 importScripts('./chunk.js')
-
node
webpack编译打包以后的代码 应用于 node环境。 非入口chunk的代码符合CMD规范。使用 chunk 时,通过 require 方法加载。
// chunk.js, 符合cmd规范 exports.ids = [0]; exports.modules = { 6: (function(module, __webpack_exports__, __webpack_require__) { ... }) } // 加载 require('./chunk')
-
async-node
webpack编译打包以后的代码 应用于 node环境。 非入口chunk的代码符合CMD规范。使用 chunk 时,通过 fs模块异步加载。
// chunk.js, 符合cmd规范 exports.ids = [0]; exports.modules = { 6: (function(module, __webpack_exports__, __webpack_require__) { ... }) } // 加载 let filename = require('path').join(__dirname, "/", 'chunk.js') require('fs').readFile(filename, 'utf-8', function(err, content) { ... }
-
node-webkit
webpack编译打包以后的代码 应用于 node-webkit环境。
node-webkit 是一个基于 Chromium 和 Node.js 的 Web 运行环境,可让你直接在 DOM 中调用 Node.js 模块,并可使用任何现有的 Web 技术来编写本地应用。
-
electron-main
webpack编译打包以后的代码 应用于 electron 主进程。
-
electron-renderer
webpack编译打包以后的代码 应用于 electron render进程。
-
elentron-preload
webpack编译打包以后的代码 应用于 electron render进程。
externals
type: string | array | object | function | RegExp
在某些情况下,我们是 不希望将依赖的类库 打包到最后输出的 bundle 中的。此时, 我们通过通过 externals配置项指定不参与编译打包的类库。
一般情况下,如果 应用程序中引入了类库,webpack 会把 类库 也 打包到输出文件 中。在 运行打包后的代码 时,会 先运行类库代码,拿到 类库 的 输出结果(exports), 然后使用 类库的结果 进行下一步操作。 ,
如果使用了 externals配置项 指定 不参与编译打包的类库,那我们在 运行打包以后的代码 时,由于 打包代码中并没有类库的代码,直接使用类库的输出结果会报错。此时我们必须 先准备好类库(先加载或者安装npm包),才能使用 类库的输出结果 进行下一步操作。
示例:
// config.js
{
externals: {
jquery: 'jQuery'
}
}
// main.js
import $ from 'jquery'
console.log($)
在上面的 示例 中,应用程序中引入的类库名(jquery) 必须和 externals配置项 中的 属性名 完全一致, 否则 externals配置项 将 无效。在 运行打包代码 时,会使用 变量jQuery 或者 通过 require('jQuery') 的方式获取 类库 的 输出结果。
使用 externals配置项 时, 会受到 output.libraryTarget配置项 和 output.globalObject配置项 的影响。
如果 output.libraryTarget 的值为 'var'、'assign', 应用程序 会通过 变量jQuery 来获取类库输出结果, 此时 当前上下文环境中 必须 存在 已定义 变量jQuery(先加载类库), 打包结果如下:
// main.js
(function(modules){
...
return __webpack_require__(__webpack_require__.s = "./src/main.js");
}({
'main': {
...
var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("jquery")
...
},
'jquery': (function(module, exports) {
module.exports = jQuery // jQuery在使用main.js前,必须已经存在
})
}))
如果 output.libarayTarget 的值为 'window', 应用程序 会通过 window["jQuery"] 来获取类库输出结果, 此时 window 对象中必须存在 已定义的属性: jQuery。
// main.js
(function(modules){
...
return __webpack_require__(__webpack_require__.s = "./src/main.js");
}({
'main': {
...
var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("jquery")
...
},
'jquery': (function(module, exports) {
// window.jQuery在使用main.js前,必须已经存在
(function() { module.exports = window["jQuery"]; }())
})
})
})
如果 output.libarayTarget 的值为 'this', 应用程序 会通过 this["jQuery"] 来获取类库输出结果, 此时 当前上下文环境对象中 必须存在 已定义的属性: jQuery。
// main.js
(function(modules){
...
return __webpack_require__(__webpack_require__.s = "./src/main.js");
}({
'main': {
...
var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("jquery")
...
},
'jquery': (function(module, exports) {
// this.jQuery在使用main.js前,必须已经存在
(function() { module.exports = this["jQuery"]; }())
})
})
})
如果 output.libarayTarget 的值为 'self', 应用程序 会通过 self["jQuery"] 来获取类库输出结果, 此时 webworker上下文环境对象中 必须存在 已定义的属性: jQuery。
// main.js
(function(modules){
...
return __webpack_require__(__webpack_require__.s = "./src/main.js");
}({
'main': {
...
var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("jquery")
...
},
'jquery': (function(module, exports) {
// self.jQuery在使用main.js前,必须已经存在
(function() { module.exports = self["jQuery"]; }())
})
})
})
如果 output.libarayTarget 的值为 'global' 且 output.globalObject 的值为 'window', 应用程序 会通过 window["jQuery"] 来获取类库输出结果, 此时 window 必须存在 已定义的属性: jQuery。
// main.js
(function(modules){
...
return __webpack_require__(__webpack_require__.s = "./src/main.js");
}({
'main': {
...
var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("jquery")
...
},
'jquery': (function(module, exports) {
// this.jQuery在使用main.js前,必须已经存在
(function() { module.exports = this["jQuery"]; }())
})
})
})
如果 output.libarayTarget 的值为 'commonjs' 、'commonjs2', 应用程序 会通过 require('jQuery') 来获取类库输出结果, 此时 jQuery包 必须已经安装。
// main.js
(function(modules){
...
return __webpack_require__(__webpack_require__.s = "./src/main.js");
}({
'main': {
...
var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("jquery")
...
},
'jquery': (function(module, exports) {
// 在使用main.js前,jQuery包必须已经安装
module.exports = require("jQuery");
})
})
})
如果 output.libarayTarget 的值为 'amd',打包结果如下:
// main.js
define(['jQuery'], function(__WEBPACK_EXTERNAL_MODULE_jquery__) {
return (function(modules){
...
return __webpack_require__(__webpack_require__.s = "./src/main.js");
}({
'main': {
...
var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("jquery")
...
},
'jquery': (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_jquery__;
})
}))
})
// requireConfig.js
require.config({
paths:{
"jQuery":'../lib/jquery.min' // 这个配置项是必须存在的, 否则会找不到jQuery
}
});
// 使用
require('./main.js', function() {...})
如果 output.libarayTarget 的值为 'umd',打包结果如下:
// main.js
(function(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
// cmd规范,应用与node环境,通过require加载类库
module.exports = factory(require("jQuery"));
else if(typeof define === 'function' && define.amd)
// amd规范, 使用requirejs加载类库, 必须有关于jQuery的require.config配置
define(["jQuery"], factory);
else {
// 一般为通过script元素的方式加载类库
var a = typeof exports === 'object' ? factory(require("jQuery")) : factory(root["jQuery"]);
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
}
}(window, function(__WEBPACK_EXTERNAL_MODULE_jquery__) {
return (function(modules){
...
return __webpack_require__(__webpack_require__.s = "./src/main.js");
}({
'main': {
...
var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("jquery")
...
},
'jquery': (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_jquery__;
})
}))
}))
externals配置项 的值的类型可以是 Object, 如下:
externals: {
// 根据output.libraryTarget的值选择使用类库的方式
jQuery: 'jQuery',
// 通过requirejs方式使用类库输出, 如果libraryTarget的值不是amd, 则没有意义
vue: 'amd Vue',
// 根据 output.libraryTarget 的值选择 加载类库时类库的名称 或者 应用类库输出结果时使用的变量
// 如果未指定, 则为 undefined
react: {
// module.exports = React_var
// 如果 libraryTarget: var 且 未指定 var: xxxx, module.exports = undefined
var: 'React_var',
// module.exports = require('React_common')
// 如果 libraryTarget: commonjs 且 未指定 commonjs: xxxx, module.exports = require (undefined)
commonjs: 'React_common',
commonjs2: 'React_common2',
// define(['React_amd'], function(obj) {...})
// 如果 libraryTarget: amd 且 未指定 amd: xxxx, define([undefined], function(obj) {...})
amd: 'React_amd',
// amd、commonjs的集合
umd: 'React_umd',
// module.exports = window[React_window]
// 如果 libraryTarget: window 且 未指定 window: xxxx, module.exports = window[undefined]
window: 'React_window',
// module.exports = self[React_window]
// 如果 libraryTarget: self 且 未指定 self: xxxx, module.exports = self[undefined]
self: 'React_self', // module.exports = self[React_self]
// module.exports = this[React_window]
// 如果 libraryTarget: this 且 未指定 this: xxxx, module.exports = this[undefined]
this: 'React_this'
}
}
externals配置项 的值的类型可以是 string, 如:
externals: 'jQuery'
// 等价与:
externals: {
jQuery: 'jQuery'
}
// 不支持 externals: 'amd jQuery'
externals配置项 的值的类型可以是 RegExp, 如:
externals: /^(jquery|\$)$/i
externals配置项 的值的类型可以是 function, 如:
// request 对应 import $ from 'jquery' 中的就juqery
externals: function(context, request, callback) {
if ( /^(jquery|\$)$/i.test(request)){
return callback(null, 'commonjs ' + request);
}
callback();
}
externals配置项 的值的类型可以是 array, 数组元素的类型可以是上面的任意一种。
performance
type: object
用于配置如何展示性能提示。例如,如果一个资源超过 250kb,webpack 会对此输出一个警告来通知你。
-
hints | false | 'warning' | 'error'
打开或关闭提示, 默认值为 'warning'。
如果 hints 的值为 false, 关闭提示。
如果 hints 的值为 warning, 当输出文件的体积超过指定体积时,输出 警告信息, 依然完成编译打包工作, 适用于 开发模式。
如果 hints 的值为 error, 当输出文件的体积超过指定体积时,中断编译打包,并输出 错误信息, 适用于 生产模式。
-
maxEntrypointSize | int
指定 入口文件 的 最大体积, 默认值为 250000 bytes。
如果 超过最大体积 且 hints 的值 不是false, 输出 警告/错误 信息。
-
maxAssetSize | int
指定 单个资源(包括入口文件) 的 最大体积,默认值为 250000 bytes。
-
assetFilter | function
自定义 哪些文件的 体积超过最大体积 时,输出 警告/错误 信息。