• webpack分环境打包(生产/开发两套打包)


    前言

    在实际开发中,开发环境和生产环境的配置有很多是相同的,例如都会配置相同的entry。考虑到代码的复用性和可维护性,我们通常要把相同的配置提取出来,以供开发环境和生产环境来使用。

    采用环境变量

    可能用的比较多的(一些配置量较少的场景)会采用环境变量判断,定义不同环境变量下不同的loaders、plugins、mode、devtool等配置,来根据变量来打包,就像这样的代码:

    const path = require('path');
    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    
    const env = process.env.NODE_ENV;
    const loaders = [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
            cacheDirectory: true,
          }
        }
      },
      {
        test: /\.jpeg$/,
        type: 'asset/resource',
      }
    ];
    const plugins = [
      new HtmlWebpackPlugin({
        template: './index.html'
      }),
      new CleanWebpackPlugin(),
    ];
    let devtool = "";
    const mode = env;
    let devServer = {};
    
    if (env === "development") {
      loaders.push(
        {
          test: /\.css|scss|sass$/,
          use: ['style-loader', 'css-loader', 'sass-loader']
        }
      )
      plugins.push(
        new CleanWebpackPlugin()
      )
      devtool = "inline-source-map";
      devServer = {
        historyApiFallback: true,
        publicPath: '/',
        open: true,
        compress: true,
        hot: true,
        port: 8888
      }
    } else {
      loaders.push(
        {
          test: /\.css|scss|sass$/,
          use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
        }
      )
      plugins.push(
        new MiniCssExtractPlugin({
          filename: 'index-[contenthash:8].css',
          chunkFilename: '[id].css'
        })
      )
      devtool = "cheap-module-source-map";
    }
    
    
    module.exports = {
      entry: './a.js',
      output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js',
        assetModuleFilename: 'static/[hash:6][ext][query]'
      },
      module: {
        rules: loaders
      },
      plugins,
      mode,
      devtool,
      devServer: {
        historyApiFallback: true,
        publicPath: '/',
        open: true,
        compress: true,
        hot: true,
        port: 8888
      },
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    可以看到,在开发环境下,我们使用css-loader解析完css文件后直接使用style-loader将其打包到bundle.js文件中;而生产环境则使用mini-css-extract-plugin插件将css文件单独抽离出来,并且分别执行了npm run buildD、npm run buildP命令打包后,产出了不同的dist文件夹。

    scripts: {
     	"buildD": "cross-env NODE_ENV=development webpack --config webpack.config.js",
        "buildP": "cross-env NODE_ENV=production webpack --config webpack.config.js",
    }
    
    • 1
    • 2
    • 3
    • 4

    开发环境的打包结果:

    在这里插入图片描述

    生产环境的打包结果:

    在这里插入图片描述

    在这个例子中,我们把开发环境和生产环境的配置项写在了同一个文件里,在项目简单时,可以接受这样的写法,但是复杂起来就会变得难以维护,针对此问题,社区所提供的的webpack-merge工具支持webpack配置文件的合并,解决了这个难题。

    采用webpack-merge

    对于大型项目,具有大量的loader、plugin时,通过环境变量、分支语句在webpack.config.js中进行配置的代码是不健全的,因此推荐使用webpack社区的webpack-merge工具,非常适合webpack文件的合并。

    npm i --save-D webpack-merge@5.7.3
    
    • 1

    现在将上面的例子进行改写,首先我们抽离出三份webpack配置文件:

    • 公共文件(相同配置汇集) webpack.config.js
    • 开发环境配置文件(开发单例) webpack.development.js
    • 生产环境配置文件(生产单例) webpack.production.js

    webpack.config.js文件内容如下:

    const path = require('path');
    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
      entry: './a.js',
      output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js',
        assetModuleFilename: 'static/[hash:6][ext][query]'
      },
      module: {
        rules: [
          {
            test: /\.js$/,
            exclude: /node_modules/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-env'],
                cacheDirectory: true,
              }
            }
          },
          {
            test: /\.jpeg$/,
            type: 'asset/resource',
          }
        ]
      },
      plugins: [
        new HtmlWebpackPlugin({
          template: './index.html'
        }),
        new CleanWebpackPlugin(),
      ],
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    webpack.development.js文件内容如下:

    const { merge } = require('webpack-merge');
    const common = require('./webpack.config.js');
    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    
    module.exports = merge(common, {
      module: {
        rules: [
          {
            test: /\.css|scss|sass$/,
            use: ['style-loader', 'css-loader', 'sass-loader']
          }
        ]
      },
      plugins: [
        new CleanWebpackPlugin(),
      ],
      devtool: "inline-source-map",
      mode: "development",
      devServer: {
        historyApiFallback: true,
        publicPath: '/',
        open: true,
        compress: true,
        hot: true,
        port: 8888
      },
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    webpack.production.js文件内容如下:

    const { merge } = require('webpack-merge');
    const common = require('./webpack.config.js');
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    
    module.exports = merge(common, {
      module: {
        rules: [
          {
            test: /\.css|scss|sass$/,
            use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
          }
        ]
      },
      plugins: [
        new MiniCssExtractPlugin({
          filename: 'index-[contenthash:8].css',
          chunkFilename: '[id].css'
        })
      ],
      devtool: 'cheap-module-source-map',
      mode: 'production'
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    最后我们在package.json中加入两种打包模式,根据目前的任务需求(开发/项目上线)来进行不同的选择打包。

    scripts: {
     	"buildD": "cross-env NODE_ENV=development webpack --config webpack.development.js",
        "buildP": "cross-env NODE_ENV=production webpack --config webpack.production.js",
    }
    
    • 1
    • 2
    • 3
    • 4

    总结

    webpack-merge工具给我们的配置文件增加了灵活性和可维护性,在之前的版本还支持merge.smart方法进行智能合并,但由于该方法要考虑的边界条件过多,在2020年开始该工具已不再支持merge.smart方法了。在我们平时的前端开发工作中,只需要最基础的merge方法,就可以很好的完成配置文件的编写工作。

  • 相关阅读:
    Oracle字符集修改
    #成为 SQL 大师#groupby 中不能有聚合函数
    【状语从句练习题】复习:分词从句
    Linux|shell编程|拷贝大文件之显示进度条
    uniapp解决scroll滑动之后被u-sticky挡住的问题
    Android 开机动画的启动过程BootAnimation(基于Android10.0.0-r41)
    探索未来金融科技 SCF新加坡举办启动盛会
    创造建材数字转型新视界,中建材如何多边赋能集团业务快速发展
    iOS开发Swift-类型转换
    第三版全球干旱指数和潜在蒸散数据发布
  • 原文地址:https://blog.csdn.net/m0_46995864/article/details/125532571