项目开发时一般需要使用两套配置文件,用于开发阶段打包(不压缩代码,不优化代码,增加效率)和上线阶段打包(压缩代码,优化代码,打包后直接上线使用)

抽取三个配置文件:

  • webpack.base.js
  • webpack.prod.js
  • webpack.dev.js

步骤如下:

  1. 将开发环境和生产环境公用的配置放入 base 中,不同的配置各自放入 prod 或 dev 文件中。
  2. 然后在 dev 和 prod 中使用 webpack-merge 把自己的配置与 base 的配置进行合并后导出
  3. 将 package.json 中的脚本参数进行修改,通过 --config 手动指定特定的配置文件

安装 webpack-merge

  1. npm i webpack-merge -D

分离

  1. project dir
  2. |_config
  3. |_webpack.base.js
  4. |_webpack.dev.js
  5. |_webpack.prod.js
  6. |_src
  7. |_package.json

webpack.dev.js

// webpack.dev.js
const merge = require('webpack-merge')
const baseConfig = require('./webpack.config.base')

const devConfig = {
  mode: 'development',
  // 配置 webpack-dev-server
  devServer: {
    open: true,
    compress: true,
    hot: true,
    port: 3000,
    contentBase: './src'
  },
  // 配置 source map
  devtool: "cheap-module-eval-source-map"
}
module.exports = merge(baseConfig, devConfig)

webpack.prod.js

const merge = require('webpack-merge')
const baseConfig = require('./webpack.config.base')

const prodConfig = {
  mode: 'production'
}

module.exports = merge(baseConfig, prodConfig)

:::danger 在 webpack 配置文件中使用绝对路径的配置,需要修改目录,比如:

  • path.join(__dirname, ‘dist’)
  • 修改为 path.join(__dirname, ‘..’, ‘dist’) :::

package.json

  "scripts": {
    "build": "webpack --config ./config/webpack.config.prod.js",
    "dev": "webpack-dev-server --config ./config/webpack.config.dev.js",
    "dev2": "webpack-dev-server",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

webpack.base.js

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const webpack = require('webpack')

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.join(__dirname, '..', '/dist/'), // <= 修改目录
    filename: "bundle.js"
  },
  plugins: [
    // 配置 html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: 'index.html', // 在内存中生成的文件名
      template: './src/index.html' // 模板,以磁盘上的这个文件为模板,不用引入 bundle.js
    }),
    // 配置 clean-webpack-plugin
    new CleanWebpackPlugin(),
    new CopyWebpackPlugin([
      {
        from: path.join(__dirname, '..', 'assets'),
        to: 'assets'
      }
    ]),
    new webpack.BannerPlugin('MangoLee!')
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'] // loader 从右向左 执行
      },
      {
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader']
      },
      {
        test: /\.s(c|a)ss$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      },
      {
        test: /\.(jpg|jpeg|png|gif|bmp)$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 5*1024, // 5kb以下的用base64编码,5kb以上的用原图片
            outputPath: 'images', // 输出到images文件夹中
            name: '[name]-[hash:4].[ext]' // 重命名
          }
        }
      },
      {
        test: /\.(woff|woff2|eot|svg|ttf)$/,
        use: 'url-loader'
      },
      {// 配置 babel
        test: '/\.js$/',
        use: {
          loader: "babel-loader",
          options: {
            presets: ['@babel/env'], // 语法预设,可以设置多个语法预设
            plugins: [
              '@babel/plugin-proposal-class-properties',
              '@babel/plugin-transform-runtime'
            ]
          }
        }
      },
      {
        test: /\.(htm|html)$/i,
        loader: 'html-withimg-loader'
      },
      {
        test: require.resolve('jquery'),
        use: {
          loader: "expose-loader",
          options: '$'
        }
      }
    ]
  },
}