Передача переменной среды в приложение Vue во время выполнения
Как я могу получить доступ к переменным среды в Vue, которые передаются в контейнер во время выполнения, а не во время сборки?
Стек выглядит следующим образом:
- VueCLI 3.0.5
- докер
- Kubernetes
Существуют предлагаемые решения для stackoverflow и в других местах для использования файла .env для передачи переменных (и использования режима), но это во время сборки и запекается в образ докера.
Я хотел бы передать переменную в Vue во время выполнения следующим образом:
- Создайте Kubernetes ConfigMap (я правильно понял)
- Передайте значение ConfigMap в переменную env K8s pod при запуске файла развертывания yaml (я правильно понял)
- Чтение из переменной env, созданной выше, например. VUE_APP_MyURL и сделайте что-нибудь с этим значением в моем приложении Vue (я не понимаю это правильно)
Я попробовал следующее в helloworld.vue:
<template>
<div>{{displayURL}}
<p>Hello World</p>
</div>
</template>
<script>
export default {
data(){
return{
displayURL:""
}
},
mounted(){
console.log("check 1")
this.displayURL=process.env.VUE_APP_ENV_MyURL
console.log(process.env.VUE_APP_ENV_MyURL)
console.log("check 3")
}
}
</script>
Я возвращаю "undefined" в журнале консоли и ничего не отображается на странице helloworld.
Я также попытался передать значение в файл vue.config и прочитать его оттуда. Тот же "неопределенный" результат в console.log
<template>
<div>{{displayURL}}
<p>Hello World</p>
</div>
</template>
<script>
const vueconfig = require('../../vue.config');
export default {
data(){
return{
displayURL:""
}
},
mounted(){
console.log("check 1")
this.displayURL=vueconfig.VUE_APP_MyURL
console.log(vueconfig.VUE_APP_MyURL)
console.log("check 3")
}
}
</script>
С vue.config выглядит так:
module.exports = {
VUE_APP_MyURL: process.env.VUE_APP_ENV_MyURL
}
Если я жестко закодирую значение в VUE_APP_MyURL в файле vue.config, оно будет успешно отображено на странице helloworld.
VUE_APP_ENV_MyURL успешно заполняется правильным значением, когда я его опрашиваю: kubectl description pod
process.env.VUE_APP_MyURL, похоже, не может успешно получить значение.
Для чего это стоит... Я могу успешно использовать process.env.VUE_APP_3rdURL для передачи значений в приложение Node.js во время выполнения.
Ответы
Ответ 1
У меня была та же проблема в моем текущем проекте, и я обнаружил, что в данный момент невозможно получить доступ к переменным среды, поэтому я в итоге решил создать файлы .env или локальные переменные среды, которые, как вы сказали, используются во время сборки.
Ответ 2
Я добавляю свое рабочее решение сюда для тех, у кого все еще проблемы. Я действительно думаю, что ответ @Hendrik M Halkow более элегантный, хотя мне не удалось решить его с помощью этого, просто из-за моего недостатка опыта в webpack и Vue. Я просто не мог понять, куда поместить конфигурацию файл и как его ссылаться.
Мой подход состоит в том, чтобы использовать переменные окружения с константами (фиктивными значениями), чтобы построить их для production
, а затем заменить эти константы в изображении, используя собственный скрипт entrypoint
. Решение выглядит следующим образом.
Я инкапсулировал все конфиги в один файл с именем app.config.js
export const clientId = process.env.VUE_APP_CLIENT_ID
export const baseURL = process.env.VUE_APP_API_BASE_URL
export default {
clientId,
baseURL,
}
Это используется в проекте просто путем поиска значения в конфигурационном файле.
import { baseURL } from '@/app.config';
Затем я использую стандартные .env. [профиль] файлы для установки переменных среды.
например .env.development
VUE_APP_API_BASE_URL=http://localhost:8085/radar-upload
VUE_APP_CLIENT_ID=test-client
Затем для производства я установил строковые константы в качестве значений.
например .env.production
VUE_APP_API_BASE_URL=VUE_APP_API_BASE_URL
VUE_APP_CLIENT_ID=VUE_APP_CLIENT_ID
Пожалуйста, не здесь значение может быть любой уникальной строкой. Просто для удобства чтения я просто заменяю имя переменной среды в качестве значения. Это будет просто скомпилировано и упаковано, как в режиме разработки.
В моем Dockerfile
я добавляю entrypoint
, который может читать эти константы и заменять их значениями переменных среды.
Мой Dockerfile выглядит следующим образом (это довольно стандартно)
FROM node:10.16.3-alpine as builder
RUN mkdir /app
WORKDIR /app
COPY package*.json /app/
RUN npm install
COPY . /app/
RUN npm run build --prod
FROM nginx:1.17.3-alpine
# add init script
COPY ./docker/nginx.conf /etc/nginx/nginx.conf
WORKDIR /usr/share/nginx/html
COPY --from=builder /app/dist/ .
COPY ./docker/entrypoint.sh /entrypoint.sh
# expose internal port:80 and run init.sh
EXPOSE 80
ENTRYPOINT ["/entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]
Затем создайте файл ./docker/entrypoint.sh, как показано ниже.
#!/bin/sh
ROOT_DIR=/usr/share/nginx/html
# Replace env vars in JavaScript files
echo "Replacing env constants in JS"
for file in $ROOT_DIR/js/app.*.js* $ROOT_DIR/index.html $ROOT_DIR/precache-manifest*.js;
do
echo "Processing $file ...";
sed -i 's|VUE_APP_API_BASE_URL|'${VUE_APP_API_BASE_URL}'|g' $file
sed -i 's|VUE_APP_CLIENT_ID|'${VUE_APP_CLIENT_ID}'|g' $file
done
echo "Starting Nginx"
nginx -g 'daemon off;'
Это позволяет мне иметь настраиваемый образ во время выполнения, который я могу запускать во многих средах. Я знаю, что это немного взломать. Но многие люди видели, как это происходит.
Надеюсь, это кому-нибудь поможет.
Ответ 3
Создайте файл config.js
с желаемой конфигурацией. Мы будем использовать это позже, чтобы создать карту конфигурации, которую мы развернем в Kubernetes. Поместите его в свой проект Vue.js, где находятся другие ваши файлы JavaScript. Хотя мы исключим его позже из минификации, полезно иметь его там, чтобы инструменты IDE работали с ним.
const config = (() => {
return {
"VUE_APP_ENV_MyURL": "...",
};
})();
Теперь убедитесь, что ваш скрипт исключен из минификации. Для этого создайте файл vue.config.js со следующим содержимым, в котором будет сохранен наш файл конфигурации.
const path = require("path");
module.exports = {
publicPath: '/',
configureWebpack: {
module: {
rules: [
{
test: /config.*config\.js$/,
use: [
{
loader: 'file-loader',
options: {
name: 'config.js'
},
}
]
}
]
}
}
}
В вашем index.html добавьте блок скрипта для ручной загрузки файла конфигурации. Обратите внимание, что файл конфигурации не будет там, поскольку мы просто исключили его. Позже мы смонтируем его из ConfigMap
в наш контейнер. В этом примере мы предполагаем, что мы будем монтировать его в тот же каталог, что и наш HTML-документ.
<script src="config.js"></script>
Измените свой код, чтобы использовать нашу конфигурацию времени выполнения:
this.displayURL = config.VUE_APP_ENV_MyURL || process.env.VUE_APP_ENV_MyURL
В Kubernetes создайте карту конфигурации, которая использует содержимое вашего файла конфигурации. Конечно, вы хотите прочитать содержимое из вашего конфигурационного файла.
apiVersion: v1
kind: ConfigMap
metadata:
...
data:
config.js: |
var config = (() => {
return {
"VUE_APP_ENV_MyURL": "...",
};
})();
Ссылка на карту конфигурации в вашем развертывании. Это монтирует карту конфигурации в виде файла в ваш контейнер. mountPath
уже содержит наш уменьшенный index.html. Мы монтируем файл конфигурации, на который мы ссылались ранее.
apiVersion: apps/v1
kind: Deployment
metadata:
...
spec:
...
template:
...
spec:
volumes:
- name: config-volume
configMap:
name: ...
containers:
- ...
volumeMounts:
- name: config-volume
mountPath: /usr/share/nginx/html/config.js
subPath: config.js
Теперь вы можете получить доступ к файлу конфигурации на <Base URL>/config.js
, и вы должны увидеть точное содержимое, которое вы поместили в запись ConfigMap. Ваш HTML-документ загружает эту карту конфигурации, так как он загружает остальную часть вашего уменьшенного кода Vue.js. Вуаля!