最近又有專案要交付,要把專案部屬到客戶測試機,這次是使用 docker compose 的方式佈署多個容器,只是在處理時就發現前端的 Nuxt3 專案有一個小小的問題:API 連結是寫在 .ts 檔案中。
以上面提到的「API 連結」為例,這個設定值除了部屬的時候以外幾乎不會修改,但是重點就是部屬的時候需要修改,如果寫死在程式中,那怕寫在一個獨立的檔案中,發布後要修改都很麻煩。所以最好的方式就是使用框架的設定值功能,方便從程式碼外部將設定值傳入。
以 Nuxt3 來說,設定值應該要寫在 nuxt.config.ts 的 defineNuxtConfig 中,可以很方便的使用 useRuntimeConfig 讀取設定值。要修改時就算是專案發布後也可以使用 .env 檔案或是設定環境變數的方式來更改設定值的內容。
另外設定值還有一個限制,就是只能是可以被序列化的資料,例如 function, Set, Map 都不能。
取得的資料如下:
和一開始提到的一樣,在網頁中沒有辦法取得到 public 以外的資料,所以 apiSecret 是 undefined
替換 port 開啟下面的網頁後就會取得 API 的回應內容
回應結果如下:
可以正常讀取到資料!
只是格式不太一樣,前面一定要使用 NUXT_ 開頭,然後其他的部分使用全部大寫加上底線('_') 分隔的 SCREAMING_SNAKE_CASE 命名方式,重新啟動服務(例如 npm run dev)後就會讀取到新的值了
(已省略部分 JSON 資料)
參考資料:
Nuxt - Runtime Config
以上面提到的「API 連結」為例,這個設定值除了部屬的時候以外幾乎不會修改,但是重點就是部屬的時候需要修改,如果寫死在程式中,那怕寫在一個獨立的檔案中,發布後要修改都很麻煩。所以最好的方式就是使用框架的設定值功能,方便從程式碼外部將設定值傳入。
以 Nuxt3 來說,設定值應該要寫在 nuxt.config.ts 的 defineNuxtConfig 中,可以很方便的使用 useRuntimeConfig 讀取設定值。要修改時就算是專案發布後也可以使用 .env 檔案或是設定環境變數的方式來更改設定值的內容。
在 defineNuxtConfig 定義設定值
在下面的程式碼中增加了 runtimeConfig ,在這裡面定義了 apiSecret 和 public.apiBase 這兩個設定值。除了這兩個設定值外還可以自己增加,只是因為安全性考量,只有在 public 區塊中的設定值才有辦法在網頁中讀取的到,其他的設定值例如 apiSecret 則是只有在 server 中可以被讀取。
export default defineNuxtConfig({
devtools: {
enabled: true
},
runtimeConfig: {
apiSecret: 'my-api-key',
public: {
apiBase: 'https://www.ruyut.com',
},
}
})
另外設定值還有一個限制,就是只能是可以被序列化的資料,例如 function, Set, Map 都不能。
讀取設定值
在網頁中讀取 public 設定值
剛建立完 Nuxt3 專案會有 app.vue ,我們直接在這裡練習:
<script setup>
const runtimeConfig = useRuntimeConfig()
console.log(`apiSecret: ${runtimeConfig.apiSecret}`)
console.log(`apiUrl: ${runtimeConfig.public.apiBase}`)
console.log(`runtimeConfig: ${JSON.stringify(runtimeConfig)}`)
</script>
取得的資料如下:
apiSecret: undefined
apiUrl: https://www.ruyut.com
runtimeConfig: {"public":{"apiBase":"https://www.ruyut.com"},"app":{"baseURL":"/","buildAssetsDir":"/_nuxt/","cdnURL":""}}
和一開始提到的一樣,在網頁中沒有辦法取得到 public 以外的資料,所以 apiSecret 是 undefined
在 Server 中讀取全部設定值
例如在之前 Nuxt3 建立 API 這篇文章中介紹的 server 中就可以讀取到全部的資料。 先依據上面的文章建立好 server/api/users.ts 檔案後,可以在裡面讀取到設定值:
export default defineNuxtConfig({
devtools: {
enabled: true
},
runtimeConfig: {
apiSecret: 'my-api-key',
public: {
apiBase: 'https://www.ruyut.com',
},
}
})
替換 port 開啟下面的網頁後就會取得 API 的回應內容
http://localhost:3000/api/users
回應結果如下:
{
"apiSecret": "my-api-key",
"apiBase": "https://www.ruyut.com",
"runtimeConfig": {
"app": {
"baseURL": "/",
"buildAssetsDir": "/_nuxt/",
"cdnURL": ""
},
"nitro": {
"envPrefix": "NUXT_",
"routeRules": {
"/__nuxt_error": {
"cache": false
},
"/_nuxt/builds/meta/**": {
"headers": {
"cache-control": "public, max-age=31536000, immutable"
}
},
"/_nuxt/builds/**": {
"headers": {
"cache-control": "public, max-age=1, immutable"
}
}
}
},
"public": {
"apiBase": "https://www.ruyut.com"
},
"apiSecret": "api_secret_token"
}
}
可以正常讀取到資料!
修改設定值
使用 .env 檔案變更設定
可以在 nuxt.config.ts 檔案的旁邊建立一個 .env 檔案,在裡面就可以變更設定值:
NUXT_API_SECRET=aaa.bbb.ccc
NUXT_PUBLIC_API_BASE=https://google.com
只是格式不太一樣,前面一定要使用 NUXT_ 開頭,然後其他的部分使用全部大寫加上底線('_') 分隔的 SCREAMING_SNAKE_CASE 命名方式,重新啟動服務(例如 npm run dev)後就會讀取到新的值了
{
"apiSecret": "aaa.bbb.ccc",
"apiBase": "https://google.com",
"runtimeConfig": {
"app": {
"baseURL": "/",
"buildAssetsDir": "/_nuxt/",
"cdnURL": ""
},
"public": {
"apiBase": "https://google.com"
},
"apiSecret": "aaa.bbb.ccc"
}
}
(已省略部分 JSON 資料)
使用環境變數變更設定
上面提到筆者這次部屬是使用 docker compose ,在執行容器時可以往服務內注入環境變數,以上面的設定值為例,假設是執行 docker 好了,可以使用下面的方式注入環境變數:
docker run -d --name my_container -p 3000:3000 -e "NUXT_API_SECRET=aaa.bbb.ccc" -e "NUXT_PUBLIC_API_BASE=https://google.com" my_docker_image
參考資料:
Nuxt - Runtime Config
留言
張貼留言
如果有任何問題、建議、想說的話或文章題目推薦,都歡迎留言或來信: a@ruyut.com