一、為何需要環境變數?
二、Quasar CLI 的環境變數
三、實作將API位置拆散到不同的環境變數設定檔(.env)
四、何謂CommonJS
五、總結
六、延伸閱讀
在專案開發,有些參數設定會因測試環境或正式環境有所區別
看到昨天src/boot/axios.js的初始化程式碼:
其中的API Base URL 就是常見的例子之一
import axios from 'axios'
export default ({ app, router, store, Vue }) => {
axios.defaults.baseURL = 'http://api.test.com.tw/'
axios.interceptors.request.use((config) => {
return config
})
Vue.prototype.$axios = axios
}
當我們使用quasar dev
、quasar build
會在我們電腦上的Node.js執行Webpack,對網頁進行編譯與打包的方式
quasar dev
,Quasar CLI會讓Webpack依照「測試環境
」的參數配置,quasar build
,Quasar CLI會讓Webpack依照「正式環境
」的參數配置,而這些環境的參數配置可以存放在哪? Node.js 的 process.env
在Quasar的官方文件提到,我們可以在專案裡面使用以下的預設環境變數
https://quasar.dev/quasar-cli/handling-process-env#Import-based-on-process.env
環境變數 | 說明 |
---|---|
process.env.DEV | Boolean Code runs in development mode |
process.env.PROD | Boolean Code runs in production mode |
process.env.CLIENT | Boolean Code runs on client (not on server) |
process.env.SERVER | Boolean Code runs on server (not on client) |
process.env.MODE | String Quasar CLI mode (spa, pwa, …) |
process.env.NODE_ENV | String Has two possible values: production or development |
讓我們來做四個小Lab,示範環境變數的變化
src/pages/Index.vue
的mounted()
裡面,透過console輸出上方四個環境變數<script>
export default {
name: 'DemoPage',
data () {
return {
}
},
mounted () {
// 是否在測試環境
console.info('process.env.DEV :', process.env.DEV)
// 是否在正式環境
console.info('process.env.PROD :', process.env.PROD)
// 當前是否在client端渲染時執行
console.info('process.env.CLIENT :', process.env.CLIENT)
// 當前是否在server端渲染時執行
console.info('process.env.SERVER :', process.env.SERVER)
// 目前是執行在哪種Quasar的專案模式
console.info('process.env.MODE :', process.env.MODE)
// 目前是執行在哪種環境?
console.info('process.env.NODE_ENV :', process.env.NODE_ENV)
}
}
</script>
這時你會得到下面的輸出結果:
quasar dev -m ssr
,以SSR的模式啟動測試伺服器src/pages/Index.vue
的mounted()
裡面,透過console輸出上方四個環境變數 (同上)這時你會得到下面的輸出結果:
前兩個Lab唯一的差別是:process.env.MODE 從原本的 spa 變成 ssr
你可能會有一個疑惑:
為什麼process.env.CLIENT 會是 true?
因為輸出console.info('process.env.CLIENT :', process.env.CLIENT)是在mounted()
mounted()是在Client端渲染
的時候執行的
這時你會得到下面的輸出結果:
可以看到和Lab-1最大的差異是
process.env.NODE_ENV 從 development
變成 production
quasar dev -m ssr
,以SSR的模式啟動測試伺服器src/pages/Index.vue
的preFetch()
裡面,透過console輸出上方四個環境變數preFetch: true
)preFetch () {
console.info('process.env.DEV :', process.env.DEV)
console.info('process.env.PROD :', process.env.PROD)
console.info('process.env.CLIENT :', process.env.CLIENT)
console.info('process.env.SERVER :', process.env.SERVER)
console.info('process.env.MODE :', process.env.MODE)
console.info('process.env.NODE_ENV :', process.env.NODE_ENV)
// console.log(this.$store.getters['example/getToken'])
// this.$store.commit('example/readToken', 'Test002')
}
重新整理網頁後,你會在終端機看到多出了這幾行訊息
和Lab-2最大的差異是,process.env.Server 變成 true
也就是說,quasar 的 preFetch() 是在Server端渲染
時執行的
現在我們要將測試環境的API網址和正式環境的API網址
分別存到.env.development 與 .env.production
測試環境
的API網址正式環境
的API網址我們可以安裝Quasar的extension @quasar/dotenv
這個套件裝完後,每當進入網站後
會在昨天談到的Quasar 初始化流程的第二個順序,幫我們存取測試環境和正式環境的.env參數
存放到process.env裡面
作法一的好處是,裝完後不需要做額外設定即可使用
缺點是,只能使用在Quasar CLI建立的專案
https://github.com/quasarframework/app-extension-dotenv/tree/dev/app-extension
quasar ext add @quasar/dotenv
2.依序回答下列問題,完成安裝
"What is the name of your .env that you will be using for development builds?"
.env.development
"What is the name of your .env that you will be using for production builds?"
.env.production
"What name would you like to use for your Common Root Object ('none' means to not use one)?"
none
"Create your .env files for you?"
yes
"For security, would you like your .env files automatically added to .gitignore?"
yes
分別在這個檔案加入API_URL=http://api.dev.com.tw
與 API_URL=http://api.production.com.tw
src/boot/axios.js
import axios from 'axios'
export default ({ app, router, store, Vue }) => {
axios.defaults.baseURL = process.env.API_URL // 從env取得API的網址
axios.interceptors.request.use((config) => {
return config
})
Vue.prototype.$axios = axios
}
<script>
export default {
name: 'DemoPage',
data () {
return {
}
},
mounted () {
this.$axios.post('login', {
username: 'username',
password: 'password'
})
}
}
</script>
分別在測試伺服器與正式伺服器打開網頁
會看到呼叫api的url網域是不一樣的 (左:測試區 右:正式區)
這個方法是自己用dot-env讀.env檔的方式
塞到quasar.config.js裡面 (Webpack的編譯設定)
相當於作法一用的套件,底層的作法
不需要依賴 Quasar CLI
dot-env
npm install — save-dev dotenv
src/config
,新增一個EnvParse.js,透過下面的程式碼,將.env的參數設定轉換成JSON的格式const DotEnv = require('dotenv')
const parsedEnv = DotEnv.config({ path: `.env.${process.env.NODE_ENV}` }).parsed
module.exports = function () {
return parsedEnv
}
比較要注意的是,quasar.config.js預設是不能使用ESModule,需要用CommonJS
而且quasar.config.js不在Webpack打包的範圍內,不用考慮Tree Shaking的問題
build: {
...
env: require('./src/config/EnvParse.js')(),
}
.env.development
與 .env.production
分別在這個檔案加入API_URL=http://api.dev.com.tw
與 API_URL=http://api.production.com.tw
src/boot/axios.js
import axios from 'axios'
export default ({ app, router, store, Vue }) => {
axios.defaults.baseURL = process.env.API_URL // 從env取得API的網址
axios.interceptors.request.use((config) => {
return config
})
Vue.prototype.$axios = axios
}
<script>
export default {
name: 'DemoPage',
data () {
return {
}
},
mounted () {
this.$axios.post('login', {
username: 'username',
password: 'password'
})
}
}
</script>
分別在測試伺服器與正式伺服器打開網頁
會看到呼叫api的url網域是不一樣的 (左:測試區 右:正式區)
早期Javascript官方沒有明定的模組規範
CommonJS 是第一次在Node.js出現的時候,用來拆分程式模組的規範
ESModule 是 ECMAScript 官方拆分模組的規範
CommonJS和ESModule除了語法上的差異之外
很多概念其實是相同的
如果想更深入的了解,可以參考下方延伸閱讀
環境變數在專案開發上真的蠻好用
還可以透過package.json的scripts
將Node_Env更改成development,以測試環境的API來打包,放在實體的測試伺服器進行測試
"scripts": {
"build:dev": "NODE_ENV=development&&quasar build",
}
專案初始化的部分大致撰寫的差不多了
之後會用一個整合的實作案例,來統整第三部分的內容
可惜連假鐵人賽沒放假
webpack 新手教學之淺談模組化與 snowpack
CommonJs 和 ESModule 的 区别整理
[Node] 環境變數設置 NODE_ENV (environment variable)