Webpack中使用環(huán)境變量的各種正確姿勢(shì)
寫在前邊
你還在為Webpack中各種打包配置而煩惱嗎?
今天我們來聊聊webpack中注入環(huán)境變量的各種姿勢(shì),或者你會(huì)覺得注入環(huán)境變量通過命令行注入不就可以了嗎?
如果你有這種想法,耐心看下去我相信你會(huì)有不一樣的收獲的~
畢竟所謂成長(zhǎng)就是一點(diǎn)一滴積累的過程!讓我們來聊聊Webpack 5中使用環(huán)境變量的各種正確姿勢(shì)。
文章中從三個(gè)方面來講解Webpack流程中的環(huán)境變量:
- 業(yè)務(wù)代碼中注入使用webpack環(huán)境變量。
- 官方提供構(gòu)建過程使用webpack環(huán)境變量。
- 傳統(tǒng)環(huán)境變量方法使用webpack構(gòu)建過程環(huán)境變量。
業(yè)務(wù)代碼使用環(huán)境變量
使用webpack.DefinePlugin插件在業(yè)務(wù)代碼中注入環(huán)境變量
相信不少同學(xué)已經(jīng)應(yīng)用過這種場(chǎng)景,我們需要在打包過程中通過webpack注入一些全局變量在業(yè)務(wù)代碼中使用。
比如我們業(yè)務(wù)入口文件有這樣一段代碼:
// src/main.js console.log('hello, Environment variable', __WEPBACK__ENV)
我們希望的是業(yè)務(wù)代碼中碰到這個(gè)__WEBPACK__ENV這個(gè)變量時(shí),代碼中會(huì)認(rèn)識(shí)這個(gè)變量并且輸出正確字符串值pacakges。
想一想我們應(yīng)該怎么做?
熟悉webpack的同學(xué)其實(shí)已經(jīng)想到了,我們可以通過webpack中的definePlugins這個(gè)插件進(jìn)行注入:
const wepback = require('webpack') // webpack.config.js ... new webpack.DefinePlugin({ __WEBPACK__ENV: JSON.stringify('packages'), TWO: '1+1', });
我們通過在webpack的plugins中加入這段配置后當(dāng)我們運(yùn)行打包命令后,此時(shí)我們業(yè)務(wù)代碼中如果出現(xiàn)__WEBPACK__ENV這個(gè)變量的話他就會(huì)幫我們替換成為'packages'這個(gè)字符串,從而達(dá)到類似環(huán)境變量注入的效果。
webpack.DefinePlugin引發(fā)的思考
或許你已經(jīng)很熟悉webpack.definePlugins這個(gè)插件的使用了,別著急讓我們耐心往下看看,由這段代碼我們引發(fā)出一下的幾個(gè)思考:
- 'packages'已經(jīng)是string類型了,為什么我們還要使用JSON.stringify()進(jìn)行處理。
- 此時(shí)的環(huán)境變量真的就是所謂的環(huán)境變量嗎?
我們先來探討一下這兩個(gè)問題:
definePlugin所謂的”環(huán)境變量“實(shí)現(xiàn)方式
webpack官方文檔中這樣講到
(Note that because the plugin does a direct text replacement, the value given to it must include actual quotes inside of the string itself. Typically, this is done either with alternate quotes, such as '"production"', or by using JSON.stringify('production').)
其實(shí)他也就是再說webpack.definePlugins本質(zhì)上是打包過程中的字符串替換,比如我們剛才定義的__WEBPACK__ENV:JSON.stringify('packages')。
在打包過程中,如果我們代碼中使用到了__WEPBACK__ENV,webpack會(huì)將它的值替換成為對(duì)應(yīng)definePlugins中定義的值,本質(zhì)上就是匹配字符串替換,并不是傳統(tǒng)意義上的環(huán)境變量process注入。
這也就回答了我們第二個(gè)問題。
JSON.stringify()處理環(huán)境變量
接下來我們來看看第一個(gè)問題,正所謂實(shí)踐出真知。我們來試試對(duì)比配置兩次不同的definePlugin來看看結(jié)果:
// webpack.config.js new webpack.DefinePlugin({ __WEBPACK__ENV: JSON.stringify('packages'), TWO: '1+1', }); // 打包后的代碼 這里我們關(guān)閉了devtools 羅列出打包后打包后的代碼 console.log('hello, Environment variable', 'packages')
// webpack.config.js new webpack.DefinePlugin({ __WEBPACK__ENV: 'packages', TWO: '1+1', }); // 打包后的代碼 這里我們關(guān)閉了devtools 羅列出打包后打包后的代碼 console.log('hello, Environment variable', packages)
仔細(xì)對(duì)比這兩段代碼第一個(gè)問題的答案其實(shí)已經(jīng)很明了了,針對(duì)definePlugin這個(gè)插件我們使用它定義key:value全局變量時(shí),他會(huì)將value進(jìn)行會(huì)直接替換文本。所以我們通常使用JSON.stringify('pacakges')或者"'packages'"。
對(duì)于DefinePlugin的流程以及需要額外注意的細(xì)節(jié)我們差不多已經(jīng)說清除了,但是此時(shí)我們定義所謂的全局變量是在業(yè)務(wù)代碼中進(jìn)行使用的。但此時(shí)如果我們對(duì)于打包構(gòu)建過程中想使用環(huán)境變量的話需要另一種方式來注入。
構(gòu)建過程中使用環(huán)境變量
通常我們?cè)谑褂脀ebpack過程中需要根據(jù)自己獨(dú)特的需求去使用環(huán)境變量進(jìn)行動(dòng)態(tài)打包,比如一些通過動(dòng)態(tài)讀取項(xiàng)目中的文件夾從而在控制臺(tái)動(dòng)態(tài)和用戶交互打包對(duì)應(yīng)不同的bundle。
此時(shí)在構(gòu)建過程中使用環(huán)境變量就顯得非常重要了,所謂構(gòu)建過程中使用環(huán)境變量簡(jiǎn)單來說就是在非業(yè)務(wù)代碼中,比如webpack.config.js配置文件中注入環(huán)境變量。
我們來看看在項(xiàng)目中輸入這行代碼:
npx webpack --env goal=local --env production --progress --config ./webpack.config.js
此時(shí)這行代碼我們相當(dāng)于運(yùn)行webpack讀取當(dāng)前目錄中的webpack.config.js配置文件進(jìn)行打包,同時(shí)注入兩個(gè)環(huán)境變量goal和progress他們的值分別為local和true。
這樣我們就可以在配置文件中使用注入的環(huán)境變量了:
const path = require('path'); module.exports = (env) => { // Use env.<YOUR VARIABLE> here: console.log('Goal: ', env.goal); // 'local' console.log('Production: ', env.production); // true return { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), }, }; };
細(xì)心的你可以已經(jīng)發(fā)現(xiàn)了,這里我們的module.exports導(dǎo)出的是一個(gè)包含env的函數(shù),而并不是傳統(tǒng)的對(duì)象了。
通常,module.exports 指向配置對(duì)象。要使用 env 變量,你必須將 module.exports 轉(zhuǎn)換成一個(gè)函數(shù)的方式進(jìn)行使用。
我們來看看如果不使用函數(shù)的話:
const path = require('path'); // Use env.<YOUR VARIABLE> here: console.log('Goal: ', process.env.goal); // undefined console.log('Production: ', process.env.production); // undefined module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), }, };
我們可以看到我們讀取node進(jìn)程process中的env.goal/production發(fā)現(xiàn)兩個(gè)分別都是undefined。
也就是說通常我們使用--env在命令行中為webpack構(gòu)建過程注入環(huán)境變量時(shí),需要將配置文件的module.exports導(dǎo)出一個(gè)函數(shù)的形式,從而在函數(shù)第一個(gè)參數(shù)中獲取對(duì)應(yīng)的key拿到對(duì)應(yīng)的環(huán)境變量value。
那么問題又來了,誒?假如我就是想在node的process中獲得對(duì)應(yīng)的環(huán)境變量呢?我應(yīng)該怎么辦,我就是不想寫一個(gè)函數(shù)。
傳統(tǒng)環(huán)境變量方法使用webpack構(gòu)建過程環(huán)境變量。
應(yīng)該怎么辦呢?其實(shí)webpack對(duì)應(yīng)打包的原理就是通過shell命令去執(zhí)行我們的配置文件(nodejs配置文件)。
假如我們?cè)谶\(yùn)行命令webpack時(shí)注入真正傳統(tǒng)意義上的環(huán)境變量而非通過--env是不是就可以了呢?接下來我們來試一試~
這里我們借助了一個(gè)非常好用的環(huán)境變量插件cross-env,它的使用方式很簡(jiǎn)單可以幫助我們?cè)诓煌h(huán)境下linux/windows...中以相同的方式去注入運(yùn)行時(shí)環(huán)境變量,接下來我們來使用一下它:
不要忘記安裝npm install --save-dev cross-env。
// package.json "build": "cross-env NAME_W=aaa webpack --config ./webpack.config.js"
我們通過cross-env NAME_W=aaa注入了一個(gè)環(huán)境變量。
// webpack.config.js console.log(process.env.NAME_W, 'env'); // 'aaa' module.exports = { entry: './src/a.js', };
在我們的嘗試下,發(fā)現(xiàn)其實(shí)通過命令行傳統(tǒng)方式注入環(huán)境變量的形式也是可以的!這樣我們就逃離了導(dǎo)出必須是一個(gè)函數(shù)的限制可以"為所欲為了"。
總結(jié)
在webpack構(gòu)建以及業(yè)務(wù)代碼中,環(huán)境變量的注入對(duì)于我們的幫助是非常大的。當(dāng)需要一定體系的前端工程化代碼時(shí),環(huán)境變量無論是在構(gòu)建過程還是業(yè)務(wù)代碼中都起到了至關(guān)重要的作用。
看到這里我們想說到的其實(shí)都已經(jīng)講到了,我們來進(jìn)行一個(gè)簡(jiǎn)單的總結(jié)吧:
在webpack打包業(yè)務(wù)代碼時(shí),我們需要使用類似環(huán)境變量的方式使用一些全局變量時(shí),可以通過webpack.DefinePlugin去定義一些變量從而在業(yè)務(wù)代碼中使用。(但是需要注意上邊講到的JSON.stringify())。
同時(shí)在構(gòu)建過程中,我們可以通過webpack官方提供的--env參數(shù)以及在配置文件中通過module.exports函數(shù)的方式使用--env定義的環(huán)境變量。
同時(shí)也可以在構(gòu)建過程中通過我們?nèi)粘J褂玫姆绞阶⑷氕h(huán)境變量而“逃脫”webpack的限制,直接使用命令行中定義的環(huán)境變量然后通過process.env.xxx去獲取。
到此這篇關(guān)于Webpack中使用環(huán)境變量的文章就介紹到這了,更多相關(guān)Webpack使用環(huán)境變量?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
jquery pagination插件動(dòng)態(tài)分頁實(shí)例(Bootstrap分頁)
這篇文章主要為大家分享了Bootstrap靜態(tài)分頁和jquery pagination插件動(dòng)態(tài)分頁兩個(gè)實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12?javascript數(shù)組中的findIndex方法?
這篇文章主要介紹了javascript數(shù)組中的findIndex方法,findIndex()?方法返回傳入一個(gè)測(cè)試條件函數(shù)符合條件的數(shù)組第一個(gè)元素位置,下面更多相關(guān)資料,需要的小伙伴可以參考一下2022-03-03HTML+CSS+JS實(shí)現(xiàn)的簡(jiǎn)單應(yīng)用小案例分享
這篇文章主要為大家分享四個(gè)用HTML+CSS+JS實(shí)現(xiàn)的簡(jiǎn)單應(yīng)用小案例,有:猜數(shù)字、表白墻、切換日夜間模式和待辦事項(xiàng),需要的可以參考一下2022-02-02JavaScript實(shí)現(xiàn)郵箱地址自動(dòng)匹配功能代碼
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)E-mail郵箱地址自動(dòng)匹配功能代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11javascript實(shí)現(xiàn)的時(shí)間格式加8小時(shí)功能示例
這篇文章主要介紹了javascript實(shí)現(xiàn)的時(shí)間格式加8小時(shí)功能,涉及javascript日期時(shí)間轉(zhuǎn)換與運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2019-06-06