Webpack设置环境变量的一些误区详解


Posted in Javascript onDecember 19, 2019

一、前言

  • 日常的前端开发工作中,至少会有两套构建环境
    • 一套开发时使用,构建结果用于本地开发调试,不进行代码压缩、打印 debug 信息、包含 sourcemap 文件等
    • 一套发布时使用,构建结果用于线上,即代码都是压缩过的、运行时不打印 debug 信息、静态文件不包括 sourcemap 等
  • webpack 4.0 版本开始引入了 mode 的概念
选项 描述
development 会将 process.env.NODE_ENV 的值设为 development。启用 NamedChunksPlugin 和 NamedModulesPlugin
production 会将 process.env.NODE_ENV 的值设为 production。启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin

二、区分开发环境/生产环境的多种方式

2.1 使用命令行

2.1.1 写法一

"scripts": {
 // 默认 mode 为 development
 "dev1": "webpack-dev-server",
 // 默认 mode 为 production,不过这样写,打包的时候会有警告
 "build1": "webpack",
}

以上 script 脚本,可以在任意模块内通过 process.env.NODE_ENV 获取当前的环境变量

但无法在 node 环境(webpack 配置文件中)下获取当前的环境变量

// index.js 
function getEnv() {
 console.log(process.env.NODE_ENV);// development | production
}

// webpack.config.js
const path = require('path');
const webpack = require('webpack');

console.log('NODE_ENV',process.env.NODE_ENV);// undefined

module.exports = {
 	entry:'./src/index.js',
  output: {
   filename: 'js/[name].js'
  },
 		...
};

2.1.2 写法二

"scripts": {
 "dev2": "webpack --mode=development",
 "build2": "webpack --mode=production",
}

和写法一, 是一样的结果

2.1.3 写法三

"scripts": {
 "dev3": "webpack-dev-server --env=development",
 "build3": "webpack --env=production",
}

以上 script 脚本,无法在任意模块内通过 process.env.NODE_ENV 获取当前的环境变量

但可以在 node 环境(webpack 配置文件中)下,通过函数获取当前环境变量

// index.js 
function getEnv() {
 console.log(process.env.NODE_ENV);// undefined
}

// webpack.config.js
const path = require('path');
const webpack = require('webpack');

console.log('NODE_ENV',process.env.NODE_ENV);// undefined

// 通过函数获取当前环境变量
module.exports = (env,argv) => {
 console.log('env',env);// development | production
 return {
 	entry:'./src/index.js',
  output: {
   filename: 'js/[name].js'
  },
 		...
 }
};

2.2 使用 mode

// index.js 
function getEnv() {
  console.log(process.env.NODE_ENV);// development | production
}

// webpack.config.js
const path = require('path');
const webpack = require('webpack');

console.log('NODE_ENV',process.env.NODE_ENV);// undefined

module.exports = {
 	mode:'development',// development | production
 	entry:'./src/index.js',
    output: {
      filename: 'js/[name].js'
    },
  		...
};

和 2.1 中的写法二,是一样的结果

一个是在命令行中设置,一个是在 webpack 配置文件中设置

2.3 使用 webpack.DefinePlugin

首先得知道这个插件的作用:设置全局变量(并非挂载到 window 上),所有模块都能读取到该变量的值

// index.js 
function getEnv() {
  console.log(process.env.NODE_ENV);// development
  console.log(NODE_ENV);// production
}

// webpack.config.js
const path = require('path');
const webpack = require('webpack');

// 这里只是凑巧和环境变量同名了,所以才不会报错
console.log('process.env.NODE_ENV',process.env.NODE_ENV);// undefined
console.log('NODE_ENV',NODE_ENV);// error !!!

module.exports = {
 	mode:'development',// development | production
 	entry:'./src/index.js',
    output: {
      filename: 'js/[name].js'
    },
 	plugins:[
      new webpack.DefinePlugin({
      	'process.env.NODE_ENV':JSON.stringify('development'),
        'NODE_ENV':JSON.stringify('production'),
    }),
  ],
  		...
};

可以在任意模块内通过 process.env.NODE_ENV 获取当前的环境变量

但无法在 node 环境(webpack 配置文件中)下获取当前的环境变量

2.4 使用 cross-env 插件

原先我一直以为这个插件,可以用来设置所有环境(浏览器环境、node 环境)下的变量。经过测试发现,只能设置node 环境下的变量 —— NODE_ENV

2.4.1 写法一

"scripts": {
 	"dev1": "cross-env NODE_ENV='production' webpack-dev-server",
    "build1": "cross-env NODE_ENV='development' webpack",
}

以上 script 脚本,可以在任意模块内通过 process.env.NODE_ENV 获取当前的环境变量

可以在 node 环境(webpack 配置文件中)下,获取当前环境变量

但是会有一个问题: 浏览器环境和 node 环境下获取到的值是不一样的

// !!!!!!
// npm run build1 
// !!!!!!

// index.js 
function getEnv() {
  console.log(process.env.NODE_ENV);// production
}

// webpack.config.js
const path = require('path');
const webpack = require('webpack');

console.log('process.env.NODE_ENV',process.env.NODE_ENV);// development

module.exports = {
 	entry:'./src/index.js',
    output: {
      filename: 'js/[name].js'
    },
  		...
};

2.4.2 写法二

"scripts": {
 "dev2": "cross-env NODE_ENV='development' --mode development",
 "build2": "cross-env NODE_ENV='production' --mode production",
}

以上 script 脚本,可以在任意模块内通过 process.env.NODE_ENV 获取当前的环境变量

可以在 node 环境(webpack 配置文件中)下,获取当前环境变量

所以在能浏览器环境下读取到环境变量的值,靠的是 mode ,在 node 环境下读取到环境变量的值,靠的是 cross-env

// !!!!!!
// npm run build2 
// !!!!!!

// index.js 
function getEnv() {
  console.log(process.env.NODE_ENV);// production
}

// webpack.config.js
const path = require('path');
const webpack = require('webpack');

console.log('process.env.NODE_ENV',process.env.NODE_ENV);// production

module.exports = {
 	entry:'./src/index.js',
    output: {
      filename: 'js/[name].js'
    },
  		...
};

三、误区

经常在一些群里看到这个问题: cross-env 和 webpack.DefinePlugin 配合使用的时候,无法通过 process.env.xxx 来获取到设置的环境变量,需要通过 webpack.DefinePlugin 里面设置的 key 来获取。

会引发这个问题的可能原因是:先往 cross-env 里设置了 NODE_ENV 变量,然后又到 DefinePlugin里设置了一遍环境变量

"scripts": {
 "dev": "cross-env NODE_ENV='development' --mode development"
}
// index.js 
function getEnv() {
  console.log(process.env.NODE_ENV);// development
}

// webpack.config.js
const path = require('path');
const webpack = require('webpack');

console.log('process.env.NODE_ENV',process.env.NODE_ENV);// development

module.exports = {
 	entry:'./src/index.js',
    output: {
      filename: 'js/[name].js'
    },
 	plugins:[
      new webpack.DefinePlugin({
       	// 设置环境变量
        	'process.env.NODE_ENV':JSON.stringify('development'),
      }),
    ],
  		...
};

此时会发现浏览器环境和 node 环境都能获取到设置的变量了,然后就认为之后再设置其他的全局变量时,也像这样写就行了。

认为 cross-env 和 DefinePlugin 是配套一起使用的,这个看法本身就很奇怪,因为两者的作用点不一样

  • DefinePlugin 的作用:是设置浏览器环境下能读取到的 "全局变量",直接通过 key 读取,在 node 环境下是无法读取到的
  • cross-env 的作用:是通过命令行设置环境变量 NODE_ENV,使 node 环境下能读取到,通过 process.env.NODE_ENV 读取
  • 如果在DefinePlugin 里设置的 key 是 process.env.NODE_ENV ,会覆盖 webpack 通过 mode 模式设置的环境变量的值
"scripts": {
 "dev": "cross-env NODE_ENV='development' --mode development"
}
// index.js 
function getEnv() {
  console.log(process.env.NODE_ENV);// 666666
}

// webpack.config.js
const path = require('path');
const webpack = require('webpack');

console.log('process.env.NODE_ENV',process.env.NODE_ENV);// development

module.exports = {
 	entry:'./src/index.js',
    output: {
      filename: 'js/[name].js'
    },
 	plugins:[
      new webpack.DefinePlugin({
        // 注意:因为同名的 key,这里的值会覆盖默认的值 !!!!!!
        	'process.env.NODE_ENV':JSON.stringify('666666'),
      }),
    ],
  		...
};

四、总结

cross-env 是专门用来设置 node 环境变量的

webpack.DefinePlugin 是专门用来设置浏览器环境下的全局变量(不会挂载到 window 上)

本文只是我个人的理解,如有错误还请告知,万分感谢

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
用javascript操作xml
Nov 04 Javascript
JS画5角星方法介绍
Sep 17 Javascript
JavaScript动态插入script的基本思路及实现函数
Nov 11 Javascript
jquery处理json数据实例分析
Jun 03 Javascript
jQuery实现首页顶部可伸缩广告特效代码
Apr 15 Javascript
高性能JavaScript循环语句和条件语句
Jan 20 Javascript
微信小程序 保留小数(toFixed)详细介绍
Nov 16 Javascript
node.js实现复制文本到剪切板的功能
Jan 23 Javascript
bootstrap插件treeview实现全选父节点下所有子节点和反选功能
Jul 21 Javascript
js根据json数据中的某一个属性来给数据分组的方法
Oct 08 Javascript
如何为vuex实现带参数的 getter和state.commit
Jan 04 Javascript
使用Cargo工具高效创建Rust项目
Aug 14 Javascript
Echarts实现多条折线可拖拽效果
Dec 19 #Javascript
js判断一个对象是数组(函数)的方法实例
Dec 19 #Javascript
利用JS如何获取form表单数据
Dec 19 #Javascript
在Vue项目中使用Typescript的实现
Dec 19 #Javascript
JS数据类型STRING使用实例解析
Dec 18 #Javascript
JS精确判断数据类型代码实例
Dec 18 #Javascript
使用webpack/gulp构建TypeScript项目的方法示例
Dec 18 #Javascript
You might like
全国FM电台频率大全 - 30 宁夏回族自治区
2020/03/11 无线电
文件上传的实现
2006/10/09 PHP
php 缓存函数代码
2008/08/27 PHP
PHP 开源框架22个简单简介
2009/08/24 PHP
隐性调用php程序的方法
2015/06/13 PHP
php类的定义与继承用法实例
2015/07/07 PHP
PHP内存缓存功能memcached示例
2016/10/19 PHP
PHP与JavaScript针对Cookie的读写、交互操作方法详解
2017/08/07 PHP
php如何比较两个浮点数是否相等详解
2019/02/12 PHP
jQuery 前的按键判断代码
2010/03/19 Javascript
JavaScript性能陷阱小结(附实例说明)
2010/12/28 Javascript
jQuery .attr()和.removeAttr()方法操作元素属性示例
2013/07/16 Javascript
javascript获取当前鼠标坐标的方法
2015/01/10 Javascript
javascript操作select元素实例分析
2015/03/27 Javascript
jQuery对JSON数据进行排序输出的方法
2015/06/24 Javascript
Bootstrap模态框调用功能实现方法
2016/09/19 Javascript
JavaScript实现的CRC32函数示例
2016/11/23 Javascript
原生JS实现简单放大镜效果
2017/02/08 Javascript
vue2.0开发入门笔记之.vue文件的生成和使用
2017/09/19 Javascript
Angular4的输入属性与输出属性实例详解
2017/11/29 Javascript
axios使用拦截器统一处理所有的http请求的方法
2018/11/02 Javascript
layui 阻止图片上传的实例(before方法)
2019/09/26 Javascript
Element-UI+Vue模式使用总结
2020/01/02 Javascript
Python高级应用实例对比:高效计算大文件中的最长行的长度
2014/06/08 Python
python使用多进程的实例详解
2018/09/19 Python
Django使用paginator插件实现翻页功能的实例
2018/10/24 Python
python实现kNN算法识别手写体数字的示例代码
2019/08/16 Python
python list多级排序知识点总结
2019/10/23 Python
Pytorch实现基于CharRNN的文本分类与生成示例
2020/01/08 Python
python matplotlib 绘图 和 dpi对应关系详解
2020/03/14 Python
sklearn和keras的数据切分与交叉验证的实例详解
2020/06/19 Python
Html5之webcoekt播放JPEG图片流
2020/09/22 HTML / CSS
非洲NO.1网上商店:Jumia肯尼亚
2016/08/18 全球购物
教师求职信范文分享
2013/12/27 职场文书
2015年营业员工作总结
2015/04/23 职场文书
CSS 新特性 contain控制页面的重绘与重排问题
2021/04/30 HTML / CSS