Webpack設(shè)置環(huán)境變量的一些誤區(qū)詳解
一、前言
- 日常的前端開(kāi)發(fā)工作中,至少會(huì)有兩套構(gòu)建環(huán)境
- 一套開(kāi)發(fā)時(shí)使用,構(gòu)建結(jié)果用于本地開(kāi)發(fā)調(diào)試,不進(jìn)行代碼壓縮、打印 debug 信息、包含 sourcemap 文件等
- 一套發(fā)布時(shí)使用,構(gòu)建結(jié)果用于線上,即代碼都是壓縮過(guò)的、運(yùn)行時(shí)不打印 debug 信息、靜態(tài)文件不包括 sourcemap 等
- webpack 4.0 版本開(kāi)始引入了 mode 的概念
| 選項(xiàng) | 描述 |
|---|---|
| development | 會(huì)將 process.env.NODE_ENV 的值設(shè)為 development。啟用 NamedChunksPlugin 和 NamedModulesPlugin |
| production | 會(huì)將 process.env.NODE_ENV 的值設(shè)為 production。啟用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin |
二、區(qū)分開(kāi)發(fā)環(huán)境/生產(chǎn)環(huán)境的多種方式
2.1 使用命令行
2.1.1 寫(xiě)法一
"scripts": {
// 默認(rèn) mode 為 development
"dev1": "webpack-dev-server",
// 默認(rèn) mode 為 production,不過(guò)這樣寫(xiě),打包的時(shí)候會(huì)有警告
"build1": "webpack",
}
以上 script 腳本,可以在任意模塊內(nèi)通過(guò) process.env.NODE_ENV 獲取當(dāng)前的環(huán)境變量
但無(wú)法在 node 環(huán)境(webpack 配置文件中)下獲取當(dāng)前的環(huán)境變量
// 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 寫(xiě)法二
"scripts": {
"dev2": "webpack --mode=development",
"build2": "webpack --mode=production",
}
和寫(xiě)法一, 是一樣的結(jié)果
2.1.3 寫(xiě)法三
"scripts": {
"dev3": "webpack-dev-server --env=development",
"build3": "webpack --env=production",
}
以上 script 腳本,無(wú)法在任意模塊內(nèi)通過(guò) process.env.NODE_ENV 獲取當(dāng)前的環(huán)境變量
但可以在 node 環(huán)境(webpack 配置文件中)下,通過(guò)函數(shù)獲取當(dāng)前環(huán)境變量
// 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
// 通過(guò)函數(shù)獲取當(dāng)前環(huán)境變量
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 中的寫(xiě)法二,是一樣的結(jié)果
一個(gè)是在命令行中設(shè)置,一個(gè)是在 webpack 配置文件中設(shè)置
2.3 使用 webpack.DefinePlugin
首先得知道這個(gè)插件的作用:設(shè)置全局變量(并非掛載到 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');
// 這里只是湊巧和環(huán)境變量同名了,所以才不會(huì)報(bào)錯(cuò)
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'),
}),
],
...
};
可以在任意模塊內(nèi)通過(guò) process.env.NODE_ENV 獲取當(dāng)前的環(huán)境變量
但無(wú)法在 node 環(huán)境(webpack 配置文件中)下獲取當(dāng)前的環(huán)境變量
2.4 使用 cross-env 插件
原先我一直以為這個(gè)插件,可以用來(lái)設(shè)置所有環(huán)境(瀏覽器環(huán)境、node 環(huán)境)下的變量。經(jīng)過(guò)測(cè)試發(fā)現(xiàn),只能設(shè)置node 環(huán)境下的變量 —— NODE_ENV
2.4.1 寫(xiě)法一
"scripts": {
"dev1": "cross-env NODE_ENV='production' webpack-dev-server",
"build1": "cross-env NODE_ENV='development' webpack",
}
以上 script 腳本,可以在任意模塊內(nèi)通過(guò) process.env.NODE_ENV 獲取當(dāng)前的環(huán)境變量
可以在 node 環(huán)境(webpack 配置文件中)下,獲取當(dāng)前環(huán)境變量
但是會(huì)有一個(gè)問(wèn)題: 瀏覽器環(huán)境和 node 環(huán)境下獲取到的值是不一樣的
// ?。。。。?!
// 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 寫(xiě)法二
"scripts": {
"dev2": "cross-env NODE_ENV='development' --mode development",
"build2": "cross-env NODE_ENV='production' --mode production",
}
以上 script 腳本,可以在任意模塊內(nèi)通過(guò) process.env.NODE_ENV 獲取當(dāng)前的環(huán)境變量
可以在 node 環(huán)境(webpack 配置文件中)下,獲取當(dāng)前環(huán)境變量
所以在能瀏覽器環(huán)境下讀取到環(huán)境變量的值,靠的是 mode ,在 node 環(huán)境下讀取到環(huán)境變量的值,靠的是 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'
},
...
};
三、誤區(qū)
經(jīng)常在一些群里看到這個(gè)問(wèn)題: cross-env 和 webpack.DefinePlugin 配合使用的時(shí)候,無(wú)法通過(guò) process.env.xxx 來(lái)獲取到設(shè)置的環(huán)境變量,需要通過(guò) webpack.DefinePlugin 里面設(shè)置的 key 來(lái)獲取。
會(huì)引發(fā)這個(gè)問(wèn)題的可能原因是:先往 cross-env 里設(shè)置了 NODE_ENV 變量,然后又到 DefinePlugin里設(shè)置了一遍環(huán)境變量
"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({
// 設(shè)置環(huán)境變量
'process.env.NODE_ENV':JSON.stringify('development'),
}),
],
...
};
此時(shí)會(huì)發(fā)現(xiàn)瀏覽器環(huán)境和 node 環(huán)境都能獲取到設(shè)置的變量了,然后就認(rèn)為之后再設(shè)置其他的全局變量時(shí),也像這樣寫(xiě)就行了。
認(rèn)為 cross-env 和 DefinePlugin 是配套一起使用的,這個(gè)看法本身就很奇怪,因?yàn)閮烧叩淖饔命c(diǎn)不一樣
- DefinePlugin 的作用:是設(shè)置瀏覽器環(huán)境下能讀取到的 "全局變量",直接通過(guò) key 讀取,在 node 環(huán)境下是無(wú)法讀取到的
- cross-env 的作用:是通過(guò)命令行設(shè)置環(huán)境變量 NODE_ENV,使 node 環(huán)境下能讀取到,通過(guò) process.env.NODE_ENV 讀取
- 如果在DefinePlugin 里設(shè)置的 key 是 process.env.NODE_ENV ,會(huì)覆蓋 webpack 通過(guò) mode 模式設(shè)置的環(huán)境變量的值
"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({
// 注意:因?yàn)橥?key,這里的值會(huì)覆蓋默認(rèn)的值 ?。。。。?!
'process.env.NODE_ENV':JSON.stringify('666666'),
}),
],
...
};
四、總結(jié)
cross-env 是專(zhuān)門(mén)用來(lái)設(shè)置 node 環(huán)境變量的
webpack.DefinePlugin 是專(zhuān)門(mén)用來(lái)設(shè)置瀏覽器環(huán)境下的全局變量(不會(huì)掛載到 window 上)
本文只是我個(gè)人的理解,如有錯(cuò)誤還請(qǐng)告知,萬(wàn)分感謝
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
JavaScript中關(guān)于數(shù)組的調(diào)用方式
這篇文章主要介紹了JavaScript中關(guān)于數(shù)組的調(diào)用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02
HTML 自動(dòng)伸縮的表格Table js實(shí)現(xiàn)
在開(kāi)發(fā)的過(guò)程中,表格Table有個(gè)缺陷,如果一行中某個(gè)單元格的超過(guò)一行,表格就不夠美觀了。2009-04-04
分享幾種比較簡(jiǎn)單實(shí)用的JavaScript tabel切換
這篇文章主要分享幾種比較簡(jiǎn)單實(shí)用的JavaScript tabel切換 的相關(guān)資料,需要的朋友可以參考下2015-12-12
javascript將數(shù)字轉(zhuǎn)換整數(shù)金額大寫(xiě)的方法
這篇文章主要介紹了javascript將數(shù)字轉(zhuǎn)換整數(shù)金額大寫(xiě)的方法,通過(guò)自定義函數(shù)中的數(shù)組替換實(shí)現(xiàn)數(shù)字轉(zhuǎn)換整數(shù)金額大寫(xiě)的功能,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-01-01
js+canvas實(shí)現(xiàn)滑動(dòng)拼圖驗(yàn)證碼功能
這篇文章主要介紹了js+canvas實(shí)現(xiàn)滑動(dòng)拼圖驗(yàn)證碼功能,本文結(jié)合實(shí)例代碼分步驟給大家介紹的非常詳細(xì),需要的朋友可以參考下2018-03-03
webpack拆分壓縮css并以link導(dǎo)入的操作步驟
我們運(yùn)行打包后會(huì)發(fā)現(xiàn)less轉(zhuǎn)為了css文件,但css文件確通過(guò)js加入style標(biāo)簽,下面我們將css進(jìn)行拆分出來(lái),并以link標(biāo)簽引入,具體實(shí)現(xiàn)步驟一起看看吧2021-10-10
解決bootstrap模態(tài)框數(shù)據(jù)緩存的問(wèn)題方法
今天小編就為大家分享一篇解決bootstrap模態(tài)框數(shù)據(jù)緩存的問(wèn)題方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
JS實(shí)現(xiàn)雙擊屏幕滾動(dòng)效果代碼
這篇文章主要介紹了JS實(shí)現(xiàn)雙擊屏幕滾動(dòng)效果代碼,涉及JavaScript鼠標(biāo)事件的響應(yīng)及頁(yè)面元素屬性的動(dòng)態(tài)變換技巧,需要的朋友可以參考下2015-10-10
微信小程序與h5的相互跳轉(zhuǎn)場(chǎng)景分析
這篇文章主要介紹了微信小程序與h5的相互跳轉(zhuǎn)場(chǎng)景分析,在微信小程序內(nèi)編寫(xiě)webview文件,通過(guò)webview去跳轉(zhuǎn)h5,loadUrl為h5的地址,非嵌套,h5需要跳轉(zhuǎn)打開(kāi)某個(gè)微信小程序,需要的朋友可以參考下2023-10-10

