以前自己写一小项目时,webpack的配置基本就是一套配置,没有考虑生产环境和开发环境的区分,最近在做一个复杂的商城项目接触到了webpack的高级配置,经过两天的研究,写出了一份目前来说比叫满意的配置,在这里分享一下。

如何区分开发环境和生产环境?

众所周知,webpack时基于node.js平台运行的,要区分开发环境和生产环境还要存,node入手。我们启动webpack时,都需要输入一些命令,npm run 、yarn start之类的,所以我们就从命令行入手,告诉webpack,当前是什么环境。

package.json

{
  \"name\": \"webpac-demo\",
  \"version\": \"1.0.0\",
  \"de ion\": \"webpack练习\",
  \"main\": \"index.js\",
  \" s\": {
    //配置开发环境参数。注意:真实开发中 package.json 文件中不能有注释
    \"dev\": \"webpack --env=development\",
    //配置生产环境参数
    \"dist\": \"webpack --env=production\",
    \"start\": \"webpack-dev-server --env=development\"
  },
  \"dependencies\": {
    \"font-awesome\": \"^4.7.0\",
    \"react\": \"^16.2.0\",
    \"react-dom\": \"^16.2.0\"
  },
  \"devDependencies\":{
  ...
  }
}

这样配置,当我们在命令行输入 npm run dev 和 npm run dist 时,就会附带一些参数到命令行中,有了参数,我们该如何拿到呢?那就要用到 node 的一个命令行参数解析引擎了。

minimist

minimist轻量级的命令行参数解析引擎

// test.js
var args = require(\'minimist\')(process.argv.slice(2));
console.log(args.hello);

$ node test.js --env=production
// production
$ node test.js --env=development
// development
$ node test.js --env
// true 注意:不是空字符串而是true

minimist会把参数解析成一个JSON对象:{key:value},有了这个JSON对象,我们就可以知道,当前的命令是要执行开发打包,还是生产打包了。

// webpack.config.js

const webpack = require(\'webpack\');
//当前项目的绝对路劲
const path = require(\'path\');

// 命令行参数解析引擎
const argv = require(\'minimist\')(process.argv.slice(2));

let env = null;

switch (argv.env) {
  case \'production\':
    //生产环境配置文件名 
    env = \'webpack.config.prod\';
    break;
  default:
    //开发环境配置文件名 
    env = \'webpack.config.dev\';

}

console.log(`当前是 ${argv.env} 打包`);

// 这时候,我们就可以加载相应的wabpack配置了。
module.exports = require( path.resolve( \'加载的配置文件路劲\',env ) );

webpack开发环境配置和生产环境配置

开发环境配置

在开发环境下,我们首先考虑的是方便开发,方便代码调试,不需要考虑代码合并和css样式分离这些。

这里主要说三个 :1.css模块化;2.模块热替换功能;3.source-map(代码映射)

// 开发环境打包配置

const path = require(\'path\');
const webpack = require(\'webpack\');
const   = require(\'./webpack.config. \')
const dfPath = require(\'./path\')
// webpack配置合并工具
const merge =require(\'webpack-merge\')


const RS = (...arg)=>path.resolve( __dirname , ...arg )

// 合并方式配置
let strategyMerge = merge.strategy({
  entry: \'prepend\'
});

let config = {
  entry: {
    app: path.resolve(dfPath.root,\'src/app.js\')
  },

  output: {
    path: dfPath.dist,
    filename: \'[name].bundle.js\',
    publicPath: \'/\',
    chunkFilename: \'[name].sepChunk.js\'
  },
  module:{
    rules: [
      {
        test: /\\.js$/,
        use:[\'babel-loader\'],
        exclude: [
          dfPath.node_modules
        ]
      },
      {
        test:/\\.css$/,
        use:[
          \'style-loader\',
          {
            loader:\'css-loader\',
            options:{
              // css模块化,方便多人开发
              module:true,
              // 定义模块化css后的类名(默认为hash值,可读性差)path:路劲; name:文件名; local:本地定义的className
              localIdentName: \'[path][name]__[local]--[hash: 64:5]\'
            },
          }
        ],
        // 排除的文件,遇到这些文件不会用当前 loader 处理,也就不会模块化
        exclude:[
          RS(\'./src/common\'),         
          RS(\'node_modules\')
        ]
      },
      {
        test:/\\.css$/,
        use:[\'style-loader\',\'css-loader\'],
        include:[
          RS(\'./src/common\'),         
          RS(\'node_modules\')
        ]
        
      },      
      
      {
        test: /\\.(png|jpg|jpeg|gif)$/,
        use: [\'url-loader?limit=8192\'],
      }
    ]
  },
  plugins:[
    // 模块热替换功能
    new webpack.HotModuleReplacementPlugin()
  ],
  
  // 代码映射,方便报错时,找到对应的源代码
  devtool: \'cheap-module-eval-source-map\',

  devServer:{
    // 服务器打包后,输出的资源路劲
    publicPath:\'/\',
    open:true
  }
};

// 导出合并后的webpack配置
module.exports = strategyMerge(   , config );

生产环境配置

相比开发环境,生产环境打包是要最后发布到服务器部署的代码,我们需要尽量保持代码简洁,加载性能最优,不需要调试辅助工具。

我们从这几个方面优化 :1.公共模块拆分,单独打包;2. css文件分离,单独打包输出;3.代码压缩;

// 生产环境配置
const webpack = require(\'webpack\');
const   = require(\'./webpack.config. \')
const path = require(\'path\');
const dfPath = require(\'./path\');
const merge = require(\'webpack-merge\');

// 压缩工具
const ClosureCompilerPlugin = require(\'webpack-closure-compiler\');
// css单独打包插件
const extractTextWebpackPlugin = require(\'extract-text-webpack-plugin\');

const extractCSS = new extractTextWebpackPlugin(\'assets/css/[name]_[contenthash:6].css\');

// weback合并配置
let strategyMerge = merge.strategy({
  entry: \'replace\',
  output: \'replace\',
  module:{
    rules: \'replace\'
  }
});

let config ={

  entry: {
    // 公共模块拆分,这些代码会单独打包,一般我们会把引用的框架文件拆分出来,方便浏览器缓存,节省资源。
    vender:[\'react\'],
    app: path.resolve(dfPath.root,\'src/app.js\')
  },
  
  output: {
    path: dfPath.dist,
    filename: \'assets/js/[name]_[chunkhash].bundle.js\',
    publicPath: \'/\',
    chunkFilename: \'assets/js/[name].sepChunk.js\',
    hashDigestLength: 6
  },

  module:{
    rules: [
      {
        test: /\\.js$/,
        use:[\'babel-loader\'],
        exclude: [
          dfPath.node_modules
        ]
      },
      /* 开启 css单独打包 和 css模块化的配置 */ 
      {
        test: /\\.css$/,
        use: extractCSS.extract({
          use: [
            {
              loader: \'css-loader\',
              options:{
                modules: true
              }              
            }
          ]
        })
      },     

      {
        test: /\\.(png|jpg|jpeg|gif)$/,
        use: [
          {
            loader: \'url-loader\',
            options:{
              limit:8192,
              name: \'[name]_[hash].[ext]\',
              outputPath: \'assets/img/\'
            }
          }
        ],
      },
      
      {
        test: /\\.(mp4|ogg|svg|ico)$/,
        use: [
          {
            loader: \'file-loader\',
            options:{
              name: \'[name]_[hash].[ext]\',
              outputPath: \'assets/media/\'
            }
          }
        ]
      },
      {
        test: /\\.(woff|woff2)(\\?v=\\d+\\.\\d+\\.\\d+)?$/,
        use: [

          {
            loader: \'url-loader\',
            options:{
              limit:10000,
              name: \'[name]_[hash].[ext]\',
              outputPath: \'assets/font/\',
              mimetype: \'application/font-woff\'
            }
          }
        ]
      },
      {
        test: /\\.ttf(\\?v=\\d+\\.\\d+\\.\\d+)?$/,
        use: [
          {
            loader: \'url-loader\',
            options:{
              limit:10000,
              name: \'[name]_[hash].[ext]\',
              outputPath: \'assets/font/\',
              mimetype: \'application/octet-stream\'
            }
          }
        ]
      },
      {
        test: /\\.eot(\\?v=\\d+\\.\\d+\\.\\d+)?$/,
        use: [
          {
            loader: \'file-loader\',
            options:{
              name: \'[name]_[hash].[ext]\',
              outputPath: \'assets/font/\',
            }
          }
        ]
      },
      {
        test: /\\.svg(\\?v=\\d+\\.\\d+\\.\\d+)?$/,
        use: [
          {
            loader: \'url-loader\',
            options:{
              limit:10000,
              name: \'[name]_[hash].[ext]\',
              outputPath: \'assets/font/\',
              mimetype: \'image/svg+ \'
            }
          }
        ]
      },

    ]
  },

  plugins:[
    extractCSS,
    
    // 设置 process.env(生产环境) 环境变量的快捷方式。
    new webpack.EnvironmentPlugin({
      NODE_ENV: \'production\'
    })    
    ,new ClosureCompilerPlugin()
  ],

  devtool: \'source-map\'
};

module.exports = strategyMerge( ,config);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

收藏 打印