webpack 基础配置摘要

一、核心概念

  • Entry:入口,webpack 执行构建的第一步将从 Entry 开始,可抽象成输入。
  • Module:模块,在 webpack 里一切皆模块,一个模块对应着一个文件。webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
  • Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。
  • Loader:模块转换器,用于把模块原内容按照需求转换成新内容。
  • Plugin:扩展插件,在 webpack 构建流程中的特定时机注入扩展逻辑来改变构建结果或做你想要的事情。
  • Output:输出结果,在 webpack 经过一系列处理并得出最终想要的代码后输出结果。

二、基础配置

2.1 entry

entry 是配置模块的入口,可抽象成输入,webpack 执行构建的第一步将从入口开始搜寻及递归解析出所有入口依赖的模块。entry 配置是必填的,若不填则将导致 webpack 报错退出。示例如下:

module.exports = {
  context: path.resolve(__dirname, 'app'),
  entry: './app/entry'
}

2.2 output

output 位于对象最顶级键(key),包括了一组选项,指示 webpack 如何去输出、以及在哪里输出你的「bundle、asset 和其他你所打包或使用 webpack 载入的任何内容」。output 是一个对象,里面包含一系列配置项,例如 path、publicPath、libraryTarget、library、chunkFilename 等等。示例如下:

module.exports = {
  output: {
    library: 'someLibName',
    libraryTarget: 'umd',
    filename: 'someLibName.js',
    auxiliaryComment: 'Test Comment'
  }
}

2.3 module

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

module.exports = {
  module: {
    rules: [
      {
        // 命中 JavaScript 文件
        test: /\.js$/,
        // 用 babel-loader 转换 JavaScript 文件
        // ?cacheDirectory 表示传给 babel-loader 的参数,用于缓存 babel 编译结果加快重新编译速度
        use: ['babel-loader?cacheDirectory'],
        // 只命中src目录里的js文件,加快 Webpack 搜索速度
        include: path.resolve(__dirname, 'src')
      },
      {
        // 命中 SCSS 文件
        test: /\.scss$/,
        // 使用一组 Loader 去处理 SCSS 文件。
        // 处理顺序为从后到前,即先交给 sass-loader 处理,再把结果交给 css-loader 最后再给 style-loader。
        use: ['style-loader', 'css-loader', 'sass-loader'],
        // 排除 node_modules 目录下的文件
        exclude: path.resolve(__dirname, 'node_modules'),
      },
      {
        // 对非文本文件采用 file-loader 加载
        test: /\.(gif|png|jpe?g|eot|woff|ttf|svg|pdf)$/,
        use: ['file-loader'],
      },
    ]
  }
}

2.4 resolve

webpack 在启动后会从配置的入口模块出发找出所有依赖的模块,resolve 配置 webpack 如何寻找模块所对应的文件,即这些选项能设置模块如何被解析。 webpack 内置 JavaScript 模块化语法解析功能,默认会采用模块化标准里约定好的规则去寻找,但你也可以根据自己的需要修改默认的规则。

module.exports = {
  resolve:{
    alias:{
      'react$': '/path/to/react.min.js'
    }
  }
}

2.5 plugins

plugins 选项用于以各种方式自定义 webpack 构建过程。webpack 附带了各种内置插件,可以通过 webpack.[plugin-name] 访问这些插件。示例如下:

const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');

module.exports = {
  plugins: [
    // 所有页面都会用到的公共代码提取到 common 代码块中
    new CommonsChunkPlugin({
      name: 'common',
      chunks: ['a', 'b']
    }),
  ]
};

2.6 devServer

webpack-dev-server 为你提供了一个简单的 web server,并且具有实时重新加载功能。

var path = require('path');

module.exports = {
  //...
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 9000
  }
};

2.7 externals

externals 配置选项提供了「从输出的 bundle 中排除依赖」的方法。

module.exports = {
  //...
  externals: {
    jquery: 'jQuery'
  }
};

三、样板文件

以下为一段来自 webpack 官方的样板配置文件:

const path = require('path');

module.exports = {
  mode: "production", // "production" | "development" | "none"  // Chosen mode tells webpack to use its built-in optimizations accordingly.
  entry: "./app/entry", // string | object | array  // 默认为 './src'
  // 这里应用程序开始执行
  // webpack 开始打包
  output: {
    // webpack 如何输出结果的相关选项
    path: path.resolve(__dirname, "dist"), // string
    // 所有输出文件的目标路径
    // 必须是绝对路径(使用 Node.js 的 path 模块)
    filename: "bundle.js", // string    // 「入口分块(entry chunk)」的文件名模板
    publicPath: "/assets/", // string    // 输出解析文件的目录,url 相对于 HTML 页面
    library: "MyLibrary", // string,
    // 导出库(exported library)的名称
    libraryTarget: "umd", // 通用模块定义    // 导出库(exported library)的类型
    /* 高级输出配置(点击显示) */  },
  module: {
    // 关于模块配置
    rules: [
      // 模块规则(配置 loader、解析器等选项)
      {
        test: /\.jsx?$/,
        include: [
          path.resolve(__dirname, "app")
        ],
        exclude: [
          path.resolve(__dirname, "app/demo-files")
        ],
        // 这里是匹配条件,每个选项都接收一个正则表达式或字符串
        // test 和 include 具有相同的作用,都是必须匹配选项
        // exclude 是必不匹配选项(优先于 test 和 include)
        // 最佳实践:
        // - 只在 test 和 文件名匹配 中使用正则表达式
        // - 在 include 和 exclude 中使用绝对路径数组
        // - 尽量避免 exclude,更倾向于使用 include
        issuer: { test, include, exclude },
        // issuer 条件(导入源)
        enforce: "pre",
        enforce: "post",
        // 标识应用这些规则,即使规则覆盖(高级选项)
        loader: "babel-loader",
        // 应该应用的 loader,它相对上下文解析
        // 为了更清晰,`-loader` 后缀在 webpack 2 中不再是可选的
        // 查看 webpack 1 升级指南。
        options: {
          presets: ["es2015"]
        },
        // loader 的可选项
      },
      {
        test: /\.html$/,
        use: [
          // 应用多个 loader 和选项
          "htmllint-loader",
          {
            loader: "html-loader",
            options: {
              /* ... */
            }
          }
        ]
      },
      { oneOf: [ /* rules */ ] },
      // 只使用这些嵌套规则之一
      { rules: [ /* rules */ ] },
      // 使用所有这些嵌套规则(合并可用条件)
      { resource: { and: [ /* 条件 */ ] } },
      // 仅当所有条件都匹配时才匹配
      { resource: { or: [ /* 条件 */ ] } },
      { resource: [ /* 条件 */ ] },
      // 任意条件匹配时匹配(默认为数组)
      { resource: { not: /* 条件 */ } }
      // 条件不匹配时匹配
    ],
    /* 高级模块配置(点击展示) */  },
  resolve: {
    // 解析模块请求的选项
    // (不适用于对 loader 解析)
    modules: [
      "node_modules",
      path.resolve(__dirname, "app")
    ],
    // 用于查找模块的目录
    extensions: [".js", ".json", ".jsx", ".css"],
    // 使用的扩展名
    alias: {
      // 模块别名列表
      "module": "new-module",
      // 起别名:"module" -> "new-module" 和 "module/path/file" -> "new-module/path/file"
      "only-module$": "new-module",
      // 起别名 "only-module" -> "new-module",但不匹配 "only-module/path/file" -> "new-module/path/file"
      "module": path.resolve(__dirname, "app/third/module.js"),
      // 起别名 "module" -> "./app/third/module.js" 和 "module/file" 会导致错误
      // 模块别名相对于当前上下文导入
    },
    /* 可供选择的别名语法(点击展示) */
    /* 高级解析选项(点击展示) */  },
  performance: {
    hints: "warning", // 枚举    maxAssetSize: 200000, // 整数类型(以字节为单位)
    maxEntrypointSize: 400000, // 整数类型(以字节为单位)
    assetFilter: function(assetFilename) {
      // 提供资源文件名的断言函数
      return assetFilename.endsWith('.css') || assetFilename.endsWith('.js');
    }
  },
  devtool: "source-map", // enum  // 通过在浏览器调试工具(browser devtools)中添加元信息(meta info)增强调试
  // 牺牲了构建速度的 `source-map' 是最详细的。
  context: __dirname, // string(绝对路径!)
  // webpack 的主目录
  // entry 和 module.rules.loader 选项
  // 相对于此目录解析
  target: "web", // 枚举  // bundle 应该运行的环境
  // 更改 块加载行为(chunk loading behavior) 和 可用模块(available module)
  externals: ["react", /^@angular\//],  // 不要遵循/打包这些模块,而是在运行时从环境中请求他们
  serve: { //object
    port: 1337,
    content: './dist',
    // ...
  },
  // 为 webpack-serve 提供选项
  stats: "errors-only",  // 精确控制要显示的 bundle 信息
  devServer: {
    proxy: { // proxy URLs to backend development server
      '/api': 'http://localhost:3000'
    },
    contentBase: path.join(__dirname, 'public'), // boolean | string | array, static file location
    compress: true, // enable gzip compression
    historyApiFallback: true, // true for index.html upon 404, object for multiple paths
    hot: true, // hot module replacement. Depends on HotModuleReplacementPlugin
    https: false, // true for self-signed, object for cert authority
    noInfo: true, // only errors & warns on hot reload
    // ...
  },
  plugins: [
    // ...
  ],
  // 附加插件列表
}

参考

Leave a Comment