webpack4 常用配置项使用整理

2,193 阅读35分钟

mode

type: string

模式配置,webpack 可根据不同的模式选择不同的 内置优化过程

production: "生产模式"。 当前模式下,部分配置项的默认值如下:

  • devTool 配置项的值为 false,不生成 .map 文件 ;

  • cache 配置项的值为 false,即 webpack 上一次编译生成的 moduleschunks 不被缓存,每次编译的时候需要重新生成 moduleschunks

  • 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

    创建 importrequire 的别名, 确保模块引入变的更加简单。

    创建模块 的时候, 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,缓存解析结果的 cachekey 中会包含 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可以 提高构建性能

    不解析的模块源文件中不应该含有 importrequiredefineurl全局变量 等。

    用法:

    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) {...})
    }])
    
    

    如果 不使用noParsevue.js 在构建 依赖关系图 时会被 解析为AST树,获取 vue 依赖的全局变量 globalsetImmediate,然后构建相应的模块。"browser"、"setImmediate"、"main"、"global" 就是解析vue模块生成的模块。如果使用了 noParse: /vue/, vue模块不会被解析,全局变量对应的模块也不会生成。

  • rules | [object]

    模块(module) 构建时, 使用 源文件url(绝对路径) 来匹配 module.rules 中的规则,为模块选择 处理源文件需要的 loader解析源文件内容需要的 parser

    module.rules 是一个 arrayrules 中的每一个 rule 是一个 object

    每一个 规则(rule) 可以分成三部分:条件(conditions)结果(results)嵌套规则(nested rules)

    条件(conditions)输入值 有两种:

    1. resource - 源文件的path(绝对路径);

    2. issuer - 发布者( issuer - A中引入B,则A是B的issuer )的path(绝对路径)

    如果 moduleresource属性 匹配 rule.testrule.includerule.excluderule.resource, 或者 moduleissuer 属性匹配 rule.issuer, 则 模块匹配当前规则rule, 可以使用 rule中的loader 处理模块。

    结果(results)输出值 有两个:

    1. loader - 应用在 resource 上的 loader数组,将 源文件 转化为 浏览器可识别的文件类型;

    2. parser option - 用于构建parser(将源文件代码解析为AST结构, 分析源文件的依赖)

    嵌套规则(nested rules) :

    可以使用属性 rulesoneOf 指定 嵌套规则。这些规则用于在 规则条件(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指定范围

      另外,testincludeexclude 之间的关系是 模块path(绝对路径)必须全部满足,才能匹配当前规则。

    • test

      Rule.testRule.resource.test缩写

      注意,使用 Rule.test 之后就不能再使用 Rule.resource,否则会 报错

      // 这种也是不允许的
      {
          test: /\.js$/,
          resource: {
              include: [path.resolve(__dirname, '../src')]
          }
      }
      
    • include

      Rule.includeRule.resource.include缩写

      注意,使用 Rule.include 之后就不能再使用 Rule.resource,否则会 报错

    • exclude

      Rule.excludeRule.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) === 0resourceQuery 提供的值一定要 精确,才能匹配成功。

      一般情况下, 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 含有 loaderoptions/query 属性;

          use: [{
              loader: 'style-loader'
          }, {
              loader: 'css-loader',
              options: {
                  minimize: true
              }
          }]
      

      use配置项 的值也可以是一个 **[string]****, 如:

          use: ['style-loader', 'css-loader']
      

      如果 use 配置项的值为 array,即 存在多个loaderwebpack会倒序使用loader处理模块。例如, use: ['style-loader', 'css-loader'], webpack 会先使用 css-loader,再使用 style-loader

      use配置项 的值也可以是一个 function,具体使用参照 官网

    • loader | string

      rule.loaderrule.use: [{loader}] 的缩写。

          loader: 'css-loader'  // 相当于 use: [{loader: ‘css-loader’}]
          
          loader: 'style-loader!css-loader' // 相当于 use: [{loader: ‘style-loader’}, {loader: ‘css-loader’}]
      
    • loaders

      rule.loadersrule.use 的别名,用法和 rule.use 完全一致。

      rule.loaderrule.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会报错。

      同时使用 loadersoptions 会报错。

      即只有 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-loaderstyle-loader 处理, .scss文件 会使用 scss-loadercss-loaderstyle-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-loaderstyle-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 loaderinline loadernormal loaderpost loader

          rules: [{
              test: /\.scss$/,
              loader: 'sass-loader'
          }, {
              test: /\.scss$/,
              loader: 'css-loader'
          }, {
              test: /\.scss$/,
              loader: 'style-loader'
          }]
      

      如果未使用 enforce属性 指定 loader优先级module收集的loaders 将按照 定义顺序倒序执行。 在上面的示例中,对于 .scss 文件, loaders 顺序为 style-loadercss-loadersass-loader,会导致 编译报错

          rules: [{
              test: /\.scss$/,
              loader: 'sass-loader',
              enforce: 'pre'
          }, {
              test: /\.scss$/,
              loader: 'css-loader'
          }, {
              test: /\.scss$/,
              loader: 'style-loader',
              enforce: 'post'
          }]
      

      使用 enforce属性 后, loaders 顺序为 css-loaderstyle-loadersass-loader, 编译成功。

      内联loader

      // loader顺序很重要
      import css from 'style-loader!css-loader!sass-loader!./styles/style.scss'
      

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

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

      所有 normal loaderpre loaderpost 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

      默认情况下,如果未指定代码分离的 chunkname, webpack会为分离的chunk自动生成 name

      例如, 从 main chunk 分离出 vendors chunk 时, 如果未指定 vendors chunkname, 新生成的 chunk 的名称为 'vendors~main'

      automaticNameDelimiter 属性会指定生成的名称之间的 连接符, 默认为 '~'

    • automaticNameMaxLength | number

      生成的chunk名称字符串的最大长度, 默认为 109

      注意: webpack4 最新版本中,该属性已废弃。

    • chunks | string | function(chunk)

      表明可以选择哪些 chunks 中的 modules 进行分离,默认值为 'async'

      代码分离之前,源文件会编译打包成两类 chunkinitial chunk (入口文件所在的chunk)async chunk (懒加载module所在的chunk)。代码分离,就是把一些满足分离条件的 module所在的chunk分离出来,然后重新生成 新的chunkchunks 会告诉我们分离的时候,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模式 下为 5development模式 下为 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

      第三步,使用 splitChunkPluginexp1 chunkexp2 chunk 中的 共享module - func1 分离出来(依据common - cache group)。 这样 main.js 中动态加载 example.1.js的时候,需要加载 common chunkexp1 chunk

      由于 maxAsyncRequests 的 值为 1, 即 按需加载example.1.js 的时候,允许的最大并行请求为 1, 则 代码分离失败,无法将 func1 moduleexp2 chunk 分离出来。

    • maxInitialRequests | number

      入口点处最大并行请求数

      production模式 下为 3development模式 下为 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 chunkcommon chunk, 这样加载首页的时候就会有 vendorscommonmain.1 三个请求。

      由于 maxInitialRequests 的值为 2, 即入口处的并行最大请求数为2, 因此 func1 modulemain.1 chunk 中分离的时候, 由于已经有 vendorsmain.1 两个chunk, 代码分离失败, 不能分离为 新的chunk

    • minChunks | number

      代码分割前必须共享模块的最小块数。即如果minChunks为3, 则 module 必须被至少三个chunk共享才能被分离出来, 默认值为 1

      注意: 如果分离出来的chunk的大小小于 minSize,则 代码分离不起作用

    • minSize | number

      指定生成块的最小大小, 以字节为单位。

      production模式 下默认为 30000字节

      development模式 下默认为 10000字节

      如果分离出来的 chunk 的大小小于 minSize, 则 代码分离不起作用

      注意:代码分离的时候如果满足 minChunksmaxInitialRequestsmaxInitialRequestscacheGroup(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 则使用 chunkindex 作为 chunk 的名称,名称为 数字

      如果 name 的值为 字符串,会使用当前字符串作为 chunk 的名称;

      如果 name 的值为 函数, 使用 函数返回字符串作为 chunk的 名称;

      如果将name的属性设置为字符串或者返回字符串的函数,源chunk分离出来的多个chunk会合并为一个chunk,可能会导致更大的初始下载量和减慢页面的加载速度。

      一般情况下,name属性更多的使用在 cacheGroup中,详见 官方文档

    • cacheGroups

      缓存组,用于指定 代码分离策略,将满足条件的 module 从原来所属的 chunk(initial chunk / async chunk) 中分离出来, 构成新的 chunkcacheGroup 可以 继承/复写splitChunks的任何配置,只有 testpriorityreuseExistingChunkcacheGroups 特有的。

      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 moduleexp1 chunkexp2 chunkutil2 chunk 共享, 将会被分离成一个 新的chunk'common'

        如果 reuseExistingChunk 的值为 true,由于 common chunk 中的 moduleutil2 chunk 中存在, 所以 util2 chunk 会被复用, common chunk 不会被新建, 最后输出的 chunk 为: main.1, main.2, exp1, exp2, util1, util2

        如果 reuseExistingChunk 的值为 falsecommon 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)。如果 enforcefalse, 由于 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模式 下, 默认为 trueproduction模式 下,默认为 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模式 下,默认为 trueproduction模式 下,默认为 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 使用 modulemodules列表 中的 index 作为 idmain.js 对应的 module id0
    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,将 modulechildren 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 chunkexample1 chunkparent

    如果 removeAvailableModulestrue, 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

    告诉 webpackprocess.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 合并包含相同 moduleschunk

    mergeDuplicateChunks 配置项会指引 MergeDuplicateChunksPlugin源文件编译打包以后的chunks 做优化,将 包含相同moduleschunks 做合并处理。优化以后的 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 chunkexample 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')。如果 chunkAchunkB子集(即chunkA中的module在chunkB中都存在), 那么 chunkBid = '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 chunkexp1 chunkexp2 chunkexp3 chunk。由于 exp3 chunk 中的 modulesexp1 chunk 中都存在, 所以 exp3 chunkexp1 chunk 的子集, exp1 chunkid'exp1, exp3'

    应用启动的时候, 会通过 动态添加script的方式 加载 exp1 chunkexp2 chunk。由于 exp1 chunkid'exp1, exp3', 所以会认为 exp1exp2exp3 都已经加载了。 这样当我们需要加载 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 moduleutil 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 moduleutil 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 被用到。

    如果 usedExporttrue, 那么 installedModules['util.js'].exports = { add: function() {...}};

    如果 usedExportfalse, 那么 util module所有输出 还是会出现中 exports 中。

    注意:如果 usedExporttrue, 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 modulemain module 会合并为一个 module;

    如果 concatenateModulesfalse, 不做 合并

    ES6模块才可以被合并。模块合并 发生在 代码分离 之后。

  • sideEffects | boolean

    用于移除 JavaScript上下文 中的 未引用代码(dead-code) - tree shaking

    product模式 下默认为 true

    为了 tree shaking 生效, 我们需要:

    • 使用 ES2015 模块语法(即 import 和 export)

    • 在项目 package.json 文件中,添加一个 "sideEffects" 入口。

    详细用法见: 官方文档

  • portableRecords | boolean

    告诉 webpack 生成 具有相对路径的记录,以便能够 移动上下文文件夹

    默认情况下,optimize.portableRecords 被禁用。

    如果至少有一个记录选项( recordsPathrecordsInputPathrecordsOutputPath)提供,则自动启用。

output

type: Obect

用于指示 webpack 如何以及在何处输出打包文件、资源以及其他使用webpack打包或者加载的文件。

  • path | string

    指定 打包文件输出目录,即打包后 文件在硬盘中的存储位置

    输出目录是一个 绝对路径

  • publicPath | string

    此选项指定在浏览器中所引用的 输出目录(path)对应的公开URL

    publicPath 并不会对 生成文件的路径 造成影响,主要是 对页面里面引入的资源的路径做对应的补全

    {
        output: {
            path: path.resolve(__dirname, '../dist'), // 打包文件会输出到path指定的位置
            publicPath: '/'  // 浏览器会访问 publicPath 指定位置的文件
        }
    }
    
  • pathinfo | boolean

    告诉 webpackchunk 中引入 所包含模块信息的相关注释

    默认值false,并且 不应该用于生产环境(production),但是 对阅读开发环境(development)中的生成代码(generated code)极其有用

    这些注释也会被添加至经过 tree shaking 后生成的 bundle 中。

  • filename | string | function

    指定 输出的打包文件文件名, 默认值为

    我们可以使用以下常用方式为每一个 打包文件 提供 唯一文件名

    • 'bundle.js' - 指定 入口文件(main.js) 所在的 chunk文件名仅适用于单页面应用

    • '[name].js' - 使用 chunkname

    • '[name].[hash].js' - 使用 compilationhash所有chunk文件名中hash值一样

    • '[name].[chunkhash].js' - 使用 chunk 内容的 hash每个chunk文件名中的hash值都不一样

    • '[name].[id].js' - 使用 chunkid

    • [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

    librarylibraryTarget 一起使用,指示将 入口文件的返回值 分配给哪个 全局对象

    默认值为 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.libraryoutput.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 为一个 RegExpvaluestringRequest 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 是一个基于 ChromiumNode.jsWeb 运行环境,可让你直接在 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

    自定义 哪些文件的 体积超过最大体积 时,输出 警告/错误 信息。