webpack开发环境和生产环境的深入理解


Posted in Javascript onNovember 08, 2018

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

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

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

package.json

{
  "name": "webpac-demo",
  "version": "1.0.0",
  "description": "webpack练习",
  "main": "index.js",
  "scripts": {
    //配置开发环境参数。注意:真实开发中 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 base = require('./webpack.config.base')
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:base64: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( base , config );

生产环境配置

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

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

// 生产环境配置
const webpack = require('webpack');
const base = require('./webpack.config.base')
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+xml'
            }
          }
        ]
      },

    ]
  },

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

  devtool: 'source-map'
};

module.exports = strategyMerge(base,config);

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

Javascript 相关文章推荐
javascript中检测变量的类型的代码
Dec 28 Javascript
表单类各种类型(文本框)失去焦点效果jquery代码
Apr 26 Javascript
js写一个字符串转成驼峰的实例
Jun 21 Javascript
JavaScript中prototype为对象添加属性的误区介绍
Oct 15 Javascript
Javascript实现颜色rgb与16进制转换的方法
Apr 18 Javascript
Jquery注册事件实现方法
May 18 Javascript
jQuery实现TAB风格的全国省份城市滑动切换效果代码
Aug 24 Javascript
react性能优化达到最大化的方法 immutable.js使用的必要性
Mar 09 Javascript
vue.js+Echarts开发图表放大缩小功能实例
Jun 09 Javascript
Angular通过angular-cli来搭建web前端项目的方法
Jul 27 Javascript
vue使用vue-cli快速创建工程
Jul 28 Javascript
详解Vue后台管理系统开发日常总结(组件PageHeader)
Nov 01 Javascript
webpack 开发和生产并行设置的方法
Nov 08 #Javascript
JS动画实现回调地狱promise的实例代码详解
Nov 08 #Javascript
深入解析ES6中的promise
Nov 08 #Javascript
vue中promise的使用及异步请求数据的方法
Nov 08 #Javascript
node使用Mongoose类库实现简单的增删改查
Nov 08 #Javascript
webpack4+express+mongodb+vue实现增删改查的示例
Nov 08 #Javascript
Echarts之悬浮框中的数据排序问题
Nov 08 #Javascript
You might like
PHP查询MySQL大量数据的时候内存占用分析
2011/07/22 PHP
微信营销平台系统?刮刮乐的开发
2014/06/10 PHP
PHP开发注意事项总结
2015/02/04 PHP
php筛选不存在的图片资源
2015/04/28 PHP
php发送邮件的问题详解
2015/06/22 PHP
ThinkPHP安装和设置
2015/07/27 PHP
PHP匿名函数和use子句用法实例
2016/03/16 PHP
jQuery Study Notes学习笔记 (二)
2010/08/04 Javascript
jQuery获取浏览器中的分辨率实现代码
2013/04/23 Javascript
extjs 如何给column 加上提示
2014/07/29 Javascript
js实现jquery的offset()方法实例
2015/01/10 Javascript
实例讲解js验证表单项是否为空的方法
2016/01/09 Javascript
jquery获取form表单input元素值的简单实例
2016/05/30 Javascript
Ionic项目中Native Camera的使用方法
2017/06/07 Javascript
React Native 自定义下拉刷新上拉加载的列表的示例
2018/03/01 Javascript
AngularJS实现动态切换样式的方法分析
2018/06/26 Javascript
jquery 动态遍历select 赋值的实例
2018/09/12 jQuery
layui 解决form表单点击无反应的问题
2019/10/25 Javascript
vue项目在webpack2实现移动端字体自适配功能
2020/06/02 Javascript
Python程序员开发中常犯的10个错误
2014/07/07 Python
python类继承与子类实例初始化用法分析
2015/04/17 Python
介绍Python中的fabs()方法的使用
2015/05/14 Python
python 执行文件时额外参数获取的实例
2018/12/18 Python
python binascii 进制转换实例
2019/06/12 Python
使用OpenCV实现仿射变换—平移功能
2019/08/29 Python
北美大型运动类产品商城:Champs Sports
2017/01/12 全球购物
澳大利亚设计的优质鞋类和适合澳大利亚生活方式的服装:Rivers
2019/04/23 全球购物
大学生水果店创业计划书
2014/01/28 职场文书
门前三包责任书
2014/04/15 职场文书
二年级语文下册复习计划
2015/01/19 职场文书
酒店工程部岗位职责
2015/02/12 职场文书
范文之农村基层党建工作报告
2019/10/24 职场文书
纯html+css实现奥运五环的示例代码
2021/08/02 HTML / CSS
Java处理延时任务的常用几种解决方案
2022/06/01 Java/Android
pandas时间序列之pd.to_datetime()的实现
2022/06/16 Python
Go中使用gjson来操作JSON数据的实现
2022/08/14 Golang