Webpack设置环境变量的一些误区详解
一、前言
- 日常的前端开发工作中,至少会有两套构建环境
- 一套开发时使用,构建结果用于本地开发调试,不进行代码压缩、打印debug信息、包含sourcemap文件等
- 一套发布时使用,构建结果用于线上,即代码都是压缩过的、运行时不打印debug信息、静态文件不包括sourcemap等
- webpack4.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
functiongetEnv(){
console.log(process.env.NODE_ENV);//development|production
}
//webpack.config.js
constpath=require('path');
constwebpack=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
functiongetEnv(){
console.log(process.env.NODE_ENV);//undefined
}
//webpack.config.js
constpath=require('path');
constwebpack=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
functiongetEnv(){
console.log(process.env.NODE_ENV);//development|production
}
//webpack.config.js
constpath=require('path');
constwebpack=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
functiongetEnv(){
console.log(process.env.NODE_ENV);//development
console.log(NODE_ENV);//production
}
//webpack.config.js
constpath=require('path');
constwebpack=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:[
newwebpack.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-envNODE_ENV='production'webpack-dev-server",
"build1":"cross-envNODE_ENV='development'webpack",
}
以上script脚本,可以在任意模块内通过process.env.NODE_ENV获取当前的环境变量
可以在node环境(webpack配置文件中)下,获取当前环境变量
但是会有一个问题:浏览器环境和node环境下获取到的值是不一样的
//!!!!!!
//npmrunbuild1
//!!!!!!
//index.js
functiongetEnv(){
console.log(process.env.NODE_ENV);//production
}
//webpack.config.js
constpath=require('path');
constwebpack=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-envNODE_ENV='development'--modedevelopment",
"build2":"cross-envNODE_ENV='production'--modeproduction",
}
以上script脚本,可以在任意模块内通过process.env.NODE_ENV获取当前的环境变量
可以在node环境(webpack配置文件中)下,获取当前环境变量
所以在能浏览器环境下读取到环境变量的值,靠的是mode,在node环境下读取到环境变量的值,靠的是cross-env
//!!!!!!
//npmrunbuild2
//!!!!!!
//index.js
functiongetEnv(){
console.log(process.env.NODE_ENV);//production
}
//webpack.config.js
constpath=require('path');
constwebpack=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-envNODE_ENV='development'--modedevelopment"
}
//index.js
functiongetEnv(){
console.log(process.env.NODE_ENV);//development
}
//webpack.config.js
constpath=require('path');
constwebpack=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:[
newwebpack.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-envNODE_ENV='development'--modedevelopment"
}
//index.js
functiongetEnv(){
console.log(process.env.NODE_ENV);//666666
}
//webpack.config.js
constpath=require('path');
constwebpack=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:[
newwebpack.DefinePlugin({
//注意:因为同名的key,这里的值会覆盖默认的值!!!!!!
'process.env.NODE_ENV':JSON.stringify('666666'),
}),
],
...
};
四、总结
cross-env是专门用来设置node环境变量的
webpack.DefinePlugin是专门用来设置浏览器环境下的全局变量(不会挂载到window上)
本文只是我个人的理解,如有错误还请告知,万分感谢
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对毛票票的支持。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。