env 環境變數的設定,通常是為為了 server 而設定的,能快速的切換狀態,但現在的網頁開始,前端的範圍逐漸往後端靠近,所以在設定,也會有 client 的變數會想要在 .env 的情況。此篇就是以 nuxt 為實作,分享此內容
最常見的 front 架構,就是把專案 build 出來之後放到,nginx 上,然後在設定上,特別聽一個 port ,讓 client request 到 server 的時候,可以 render 出你要的畫面。
下列為一個簡單的 nginx 設定範例:
# 設定 server port
upstream be_server {
server 127.0.0.1:9990;
}
# listen port
location / {
proxy_pass http://be_server/;
}
在這樣子的情況, .env 的 file 是放在 server 上,所以 client 要拿到,是沒有辦法的,如果說在專案中,把 env 放到 nuxt.config.js 中去作設定的話,在 build 完的時候,資料會被寫死在 .output/server/chunks/nitro/node-server.mjs 的 檔案中,可以在變數 _inlineRuntimeConfig 上看到你所設定的變數。
不過我們來看一下面提到的一種 build & deploy 的情況。
參考下面部署的示意圖,今天有三台機要部署放著同一個專案,如果讓每台都執行 run build 的 script ,那每台機器就會浪量的資源在 build 上面,但如果可以把 build 的這件事情,放到一台機器上,最後只要把 dist 的檔案放到 server 上就可以 work 了。但是…這也遇到了一個問題。
如果說今天同樣的專案,但是它是只需要吃不同的 .env ,這樣子難道就真的一定要 build 到三次嗎?
所以如果可以在 run start 專案的時候,可以拿到最即時的 .env 就是一件很重要的事情。可以為你多爭取到一杯咖啡的時間。
其實這個解法很簡單,只要專案在 start 後,可以從 api 中或是 file 中,拿到最新的 env 的資料,而不是透過 runconfig 所設定的資料,這樣子靈活性也會變高需多。
所以我們實作的羅輯是在前端的專案中寫一個可以 get env 的 api ,在專案 init 的時候就向它發出 request 取得資料,放到 nuxt 中獨有的 useState 中,讓 client 能直接取得 env,如果 env 更新的情況下,也只需要 restart 就可以拿新的 env 資料。
這邊我選擇在 middleware 的時候來發出 request
// src/middleware/env.global.ts
export default defineNuxtRouteMiddleware(async (to, from) => {
const { data: env } = await useFetch("/api/env");
useState("env", () => env);
});
<script setup lang="ts">
const env = useState('env')
</script>
// src/server/api/env.get.ts
import * as dotenv from "dotenv";
dotenv.config();
export default defineEventHandler(() => {
const env = { NUXT_PORT: process.env.NUXT_PORT };
return env;
});
寫程式寫的越久,就會發現一個好的網站,一個好的開發流程,是需要額外作需多的事情。實在沒有辦法透過一個人獨立完成。
未來還有多少的東西需要去學習呢?就讓我繼續學下去吧~~ (嘆氣)