webpack 2 config 文件入门

webpack.config.js 的基本结构

var path = require('path')

module.exports = {
  entry:  {
    home: './home.js',
    about: './about.js',
    contact: './contact.js',
  }, // 入口文件
  // string | [string] | object {<key>: string | [string] }
  // 一个页面搭配一个入口文件
  output: {
    // output 包含一系列关于打包后文件的配置
    // output.chunkFilename: string, 这个参数确定了加载 chunk 的名称
    // output.crossOriginLoading: boolean | string, 只在 target 参数指定为 web 的时候使用, 因为此时通过 jsonp 加载模块
    // crossOriginLoading: false(default) , 禁止跨域加载
    // crossOriginLoading: 'anonymous', 允许无 credential 的跨域加载
    // crossOriginLoading: 'use-credentials', 允许有 credential 的跨域加载
    //
    // output.devtoolFallbackModuleFilenameTemplate: string | function(info)
    // output.hotUpdateChunkFilename: string, 指定热刷新的 chunk 的名称, 仅支持 id 和 hash 占位符
    // hotUpdateChunkFilename: '[id].[hash].hot-update.js'
    // output.sourceMapFilename: string, 仅当 devtool 使用 source map 时生效, 默认为[ file].map, 可选占位符有[name], [id], [hash], [chunkhash]

    path: path.resolve(__dirname, 'dist'), // 打包后文件存储路径, 必须是绝对路径, 可以用 path 模块生成

    publicPath: /assert/, // 解析文件中相对路径时依赖的根目录
    // 该字段设定了输出文件的 public Url
    //
    // 默认的, 相对路径会基于 html 文件位置或<base>标签进行解析, 添加 publicPath 后, 各个 loaders 会在每个相对路径前添加 publicPath, 即相对路径基于 publicPath 进行解析
    // 该值一般以'/'结尾
    // 默认值为''
    // simple rule: 该参数的值为html 页面到 output.path 的相对值
    // path: path.resolve(__dirname, 'public/assets'),
    // publicPath: 'https://cdn.example.com/assets/',
    // publicPath 也会对 webpack-dev-server 生效
    // publicPath: 'https://cdn.example.com/assets/' cdn, 并且应该使用 https
    // publicPath: '//cdn.example.com/assets/', cdn, 使用相同协议
    // publicPath: '/assets/', 相对于服务器根路径
    // publicPath: 'assets/', 相对于 html 页面
    // publicPath: '../assets/', 相对于 html 页面
    // publicPath: '', 相对于 html 页面(同一路径)

    filename: 'bundle.js', // 打包后的文件名称
    // 对于单一入口文件, filename 可以为静态名称'bundle.js'
    // 对于多入口文件, 可以使用参数生成特定名称
    // [name], [id], [hash], [chunkhash]
    // 可以为文件添加路径: 'js/[name]/bundle.js'

    library: 'MyLibrary', // 输出库的名称

    libraryTarget: 'umd', // 输出库的类型
  },
  module: {
    // module.noParse: RegExp | [RegExp], 符合正则的字段被 import, require, define 后不会被处理, 可以提高打包速度
    // noParse: /jquery|lodash/
    //
    rules: [
      // 模块应用规则(loaders, parser 的设定等)
      // module.rules: array
      // 一条 Rule 可以分为三部分, Conditions, Results, Nested Rules

      // Conditions, 有两个输入值,
      // 1\. The resource: 文件引用的绝对路径经过 resolve 规则解析后的结果
      // 2\. The issuer: 引用 resource 的模块到文件的绝对路径
      // 比如, 'app.js' 中 'import ./style.css', resource 是 '/path/to/style.css', issuer 是 '/path/to/app.js'
      // 在 rule 中, test, include, exclude 和 resource 作用于resource, 而 issuer 族谱用于 issuer

      // Results
      // Rule Results 仅在 Rule Conditions 满足时起作用
      // Rule Results 有二种输出值
      // Applied Loaders: 一个数组, 其元素是应用于 resource 的 loaders
      // Parser options: 一个 options 对象, 作为当前 module 的 parser
      // loader, options, use 用于 loaders,
      // query, loaders 用于提高兼容性
      // enforce 属性指定 loader 类型, 可选值有: normal, pre, post
      // parser 属性影响 parser options

      // Nested Rules
      // 在 rules 和 oneOf 属性中可以指定 nested rules

      // Rule.enforce: 'pre' | 'post', 指定 loader 的类型, 默认为 normal
      // 还有一种 inline loader 应用于 inline import/require,
      // 所有 loaders 按照 post, inline, normal, pre 排序并依次执行
      // 所有 normal loaders 可以通过在 request 中添加前缀 '!' 进行忽略
      // 所有 normal 和 pre loaders 可以通过在 request 中添加前缀 '-!' 进行忽略
      // 所有 normal, post 和 pre loaders 可以通过在 request 前添加 '!!' 进行忽略

      // Rule.exclude
      // Rule.exclude 是 Rule.resource.exclude 的缩写
      //
      // Rule.include
      // Rule.include 是 Rule.resource.include 的缩写
      //
      // Rule.issuer
      //
      // Rule.loader
      // Rule.loader 是 Rule.use: [{loader}] 的别名
      //
      // Rule.loaders
      // Rule.loaders 是 Rule.use 的别名, 他的存在仅为了兼容 webpack1, 应使用 Rule.use
      //
      // Rule.oneOf
      // 一个数组, 其元素为一系列 rules, 仅第一个符合条件的 rule 会起作用
      //
      // Rule.options/ Rule.query
      // Rule.options 和 Rule.query 都是 Rule.use: [{options}] 的缩写
      // Rule.query 的存在仅为了兼容 webpack1, 应使用 Rule.options
      //
      // Rule.parser
      // 一个 parser options 的对象, 所有要使用的 parser options 都集中在此
      // 每个不同的 parser options 都会创建对应 parser, 并且 plugins 可以根据 parser options 应用.  当 parser options 中没有设置或设置为 true 时, 大部分 plugins 默认只应用他们自己的 parser plugins
      // parser: {
      // amd: false, // disable AMD
      // commonjs: false, // disable CommonJS
      // harmony: false, // disable ES6 Harmony import/exports
      // requireInclude: false, // disable require.include
      // requreEnsure: false, // disable require.ensure
      // }

      // Rule.resource
      // Rule.rules, 一个 Rules 组成 的数组
      // Rule.test, Rule.resource.test 的缩写
      // Rule.use, 一系列应用于 modules 的 UseEntries, 每一个 entry 指定一个 loader
      // use: ['style-loader'] 是 use: [{loader: 'style-loader'}] 的缩写
      // 可以链式传入多个 loaders, 从右向左依次执行
      // use: [
      //   {loader: 'style-loader'},
      //   {loader: 'css-loader', options: { importLoader: 1}},
      //   {loader: 'less-loader', options: { noIeCompat: true}},
      // ]

      // Condition
      // Condition 可以为以下之一:
      // String: 比如 exclude: 'node_modules'
      // RegExp: 比如 test: /\.js$/, exclude: /node_modules/
      // function: 返回 true 或 false
      // Condition Array: 至少有一个满足时刻认为满足 condition
      // Object: 所有属性都满足时可认为满足
      //
      // {test: Condition}, {include: Condition}, {exclude: Condition}, {and: [Condition]}, {or: [Condition]}, {not: Condition}
      //
      // UseEntry: object
      // 该属性必须有一个字符串 loader.
      // 该属性相对 context 的值解析 loader
      // 该属性拥有 options 属性, 该属性为 string 或 object, 该属性会作为 loader options 被传给 loader
      // 考虑到兼容性, 目前仍支持 query 作为 options 的别名
      //

      {
        test: /\.jsx?$/, // 通过正则表达式选择要处理的文件
        include: [ // 限定文件范围
          path.resolve(__dirname, 'app')
        ],
        exclude: [ // 排除文件范围
          path.resolve(__dirname, 'demo')
        ]
        // 最佳实践
        // test 中使用正则表达式
        // include 和 exclude 中使用绝对路径
        // 优先使用 include 而不是 exclude
        issuer: { test, include, exclude },
        // issuer 的应用范围
        enforce: 'pre',
        enforce: 'post',
        loader: 'babel-loader',
        // 使用 babel-loader 处理符合条件的文件
        // webpack2 中 -loader 不再可以省略
        options: {
          presets: ['es2015']
        }
        // babel-loader 的配置
      },
      {
        test: /\.html$/,
        use: [
          // 应用多个 loader 及相关配置
          'htmllint-loader',
          {
            loader: 'html-loader',
            options: {
              // ...
            }
          }
        ]
      },

      {
         oneOf: [ /* rules */ ],
         // 仅应用 rules 数组中的一条规则
      },

      {
        rules: [ /* rules */ ],
        // 应用所有 rules
      },

      {
        resource: { and: [ /* conditions */ ]}
        // 当所有 conditions 都满足时才认为符合条件
      },

      { resource: { or: [ /* conditions */ ]}, },
      { resource: [ /* conditions */] },
      // 当某一 condition 满足时即可认为符合条件

      {
        resource: { not: /* condition */ }
        // 当某一 condition 不满足时可认为符合条件
      }
    ],
    // rules 结束
  },
  resolve: {
    // 解析模块 request 时的配置
    // (不会应用于解析 loader )
    modules: [
      'node_modules',
      path.resolve(__dirname, 'app')
    ],
    // 解析 modules 时的路径
    extensions: ['.js', '.json', '.jsx', '.css'],
    // 可以省略的扩展名
    alias: {
      // 模块别名
      // 为 import 或 require 创建别名
      // Utilities: path.resolve(__dirname, 'src/utilities')
      // import Utility from '../../utilities/utility' 可以缩写为
      // import Utility from 'Utilities/utility'
      // 末尾添加$可以进行精确匹配, 类似正则
      //
      'module': 'new-module',
      // 别名 module 可以表示 new-module, 包括文件与路径, 比如 module/path/file 会被解析为 new-module/path/file
      'only-module$': 'new-module',
      // 别名 only-module(处于尾部) 会被解析成 new-module, 因此 module/path/file 不会被解析
    },
    // aliasFields: string
    // 指定一个 field, 比如 browser, 来执行特定的 alias
    // aliasFields: ['browser']
    //
    // resolve.descriptionFiles: array
    // 用于描述的 JSON 文件, 默认为
    // descriptionFiles: ['package.json']
    //
    // resolve.enforceExtension: boolean
    // 如果为 true, webpack 不会处理没有扩展名的文件, 默认为 false, 及允许 require('./foo') 这种写法
    //
    //resolve.enforceModuleExtension: boolean
    //默认为 false, 是否允许 modules(loaders) 省略扩展名
    //
    //resolve.extensions: array, 自动解析指定的扩展名
    //默认为
    // extensions: ['.js', '.json']
    // 因此可以使用 import File from ('../path/to/file') 这种写法
    //
    // resolve.mainFields: array
    // 当 import 一个包时, 比如 import * as D3 from 'd3', 这个设置决定package.json中的哪个 field 对应的包的会被检索, 默认值基于 target 的值
    // 当 target 指定为 webworker, web 或不指定
    // mainFields: ['browser', 'module', 'main']
    // 对于其他 target,
    // mainFields ['module', 'main']
    // 例如, D3的 package 包括这些 fields
    // {
    // ...
    // main: 'build/d3.Node.js',
    // browser: 'build/d3.js',
    // module: 'index'
    // ...
    // }
    //
    // resolve.mainFiles: array
    // 这里的 filename 会在解析路径的时候用到, 默认为
    // mainFiles: ['index']
    //
    // resolve.modules: array
    // 限定 webpack 搜索与解析的范围
    // 可以使用绝对路径偶相对路径, 但是他们的行为有少许不同.
    // 相对路径的检索方式与 Node 检索 module 相近, 首先检索当前路径及父路径
    // 绝对路径则只会检索给定路径
    // 默认值为 modules: ['node_modules']
    //
    // 如果要添加路径, 应当添加在 node_modules 前面
    // modules: [path.resolve(__dirname, 'src'), 'node_modules']
    //
    // resolve.unsafeCache: regex | array | boolean
    // 默认为 true, 即允许模块缓存, 即使这种行为是不安全的
    //
  },

  performance: {
    // 此配置决定 webpack 的通知功能
    // 主要用于对文件尺寸的控制
    hints: 'warning', // enum
    // hints: boolean | 'error' | 'warning'
    // 设定 webpack 何时显示通知
    // 默认为 warning

    maxAssetSize: 200000, // int (in bytes)
    // maxAssetSize: int, 这个选项限制了单个 asset 的尺寸, 默认为250000

    maxEntrypointSize: 400000, // int (in bytes)
    // maxEntrypointSize: int, 限制初始加载时单个 entry 的最大请求数, 默认为250000

    assetFilter: function (assetFilename) {
      return assetFilename.endsWith('.css') || assetFilename.endsWith('.js')
    }
    // assetFilter: function, 这个属性允许 webpack 控制使用哪些文件来计算 performance hint, 默认为
    // function (assertFilename) {
    //   return !(/\.map$/.test(assetFilename))
    // }
    //
    // 可以自己设定 filter function
    // assetFilter: function(assetFilename) {
    //   return assetFilename.endsWith('.js')
    // }
  },

  devtool: 'source-map', // enum, string | false
  // 可以提高 debug 的便利性, 但是会影响打包速度
  // 面向开发有: eval, inline-source-map, eval-source-map, cheap-module-eval-source-map
  // 面向生产有: source-map, hidden-source-map, cheap-source-map, nosources-source-map

  context: __dirname, // 使用绝对路径
  // webpack 的根路径, loaders 的配置文件(.babelrc, postcss.config.js)和 entry 都是基于 context 来解析的
  // 该属性值默认为当前目录, 但是强烈建议书写这一字段, 可以使你的配置文件独立于当前工作目录

  target: 'web', // enum
  // 打包文件运行环境
  // webpack 可以针对多个 environment 或 target 编译
  // target: string, (async-node|electron|electron-renderer|node|node-webkit|web|webworker)

  externals: ['react', /^@angular\//],
  // 不必打包的内容
  // externals: string| RegExp | function | array | object
  // 例如要使用 jquery 的 cdn, 则可以这样配置
  // externals: {
  //   jquery: 'jQuery'
  // }
  // import $ from 'jquery'
  //
  // externals: {
  //   substract: ['./math', 'substract']
  // }
  // 会形成一个负责结构, ./math 是父模块, 而你的 bundle 仅请求其子模块 substract
  //
  // externals: {
  //   react: 'react',
  //   lodash: {
  //     commonjs: 'lodash',
  //     amd: 'lodash',
  //     root: '_'
  //   }
  // }
  //

  watch: boolean
  // webpack 可以监控文件并在他们变化时进行重新编译
  // 默认为 false

  watchOptions: object,
  // 配置 watch 的模式
  // {
  //   aggregateTimeout: number, 从第一次检测到文件变化到进行重新编译的延迟时间, 这个段时间内的其他变化会被整合进此次编译
  //   ignored: string | RegExp, 忽视某些文件的变化, 减轻 CPU 负担
  //   poll: boolean | number, 每隔1000ms 进行一次检测
  // }

  stats: {
    // 待补充
  },

  devServer: {
    // 这一部分的设置会被 webpack-dev-server 采用
    contentBase: path.resolve(__dirname, 'dist'), // 指定 serve 目录为 dist
    compress: true, // 开启 gzip 压缩
    port: 9000, // 指定端口
    // 当 devServer 启动时, 控制台会打印
    // http://localhost:9000
    // webpack result is served from /build/
    // content is served from dist/
    // 这几行指出了 server 的位置和 served 内容
    // 如果你使用了 Node.js API, 那么这部分会被忽略
    //
    // devServer.filename: string, 这个选项可以减少 lazy mode 下的编译次数
    // 默认的, 在 lazy mode 下, 每一个请求会进行一次新的编译
    // 添加 filename 后, devServer 仅在请求 filename 时进行编译, 比如
    // lazy: true,
    // filename: bundle.js
    // 此时, devServer 仅在请求/ bundle.js 时进行编译
    // filename 仅在 lazy mode 中起作用
    // devServer.headers: object, 在所有 request 中添加请求头
    // headers: {
    //   'X-Custom-Foo': 'bar'
    // }
    //
    // devServer.historyApiFallback: boolean, object
    // 当使用 Html5 History Api 时, index.html 可能得到404响应
    //
    // devServer.hot: boolean, 开启 webpack 模块热替换
    //
    // devServer.host - CLI only
    // 指定 host
    //
    // devServer.https: boolean | object, devServer 默认false, 即使用 http
    //
    // devServer.inline - CLI only
    // 切换 devServer 的模式, 默认使用 inline 模式, 即脚本会直接注入到你的 bundle 以实现重载, 设置 devServer.inline: false 可以启用 iframe 模式
    //
    //
  },

  plugins: [
    // 待补充
  ]
}