在运行时将环境变量传递给 Vue 应用程序

新手上路,请多包涵

我如何访问 Vue 中的环境变量,这些变量是在运行时而不是在构建期间传递给容器的?

堆栈如下:

  • VueCLI 3.0.5
  • 码头工人
  • 库伯内斯

在 stackoverflow 和其他地方有建议的解决方案使用 .env 文件传递变量(和使用模式),但那是在构建时并被烘焙到 docker 图像中。

我想在运行时将变量传递给 Vue,如下所示:

  • 创建 Kubernetes ConfigMap(我做对了)
  • 运行部署 yaml 文件时将 ConfigMap 值传递到 K8s pod 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>

我在控制台日志中返回“未定义”,并且在 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.config 文件中将一个值硬编码到 VUE_APP_MyURL 中,它会在 helloworld 页面上成功显示。

当我询问 VUE_APP_ENV_MyURL 时,它已成功填充了正确的值:kubectl describe pod

process.env.VUE_APP_MyURL 似乎没有成功检索到该值。

对于它的价值……我能够在运行时成功地使用 process.env.VUE_APP_3rdURL 将值传递到 Node.js 应用程序。

原文由 Johann 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.6k
2 个回答

使用所需的配置创建一个文件 config.js 。稍后我们将使用它来创建我们部署到 Kubernetes 的配置映射。将它放入其他 JavaScript 文件所在的 Vue.js 项目中。虽然我们稍后会将其从缩小中排除,但将其放在那里很有用,这样 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="<%= BASE_URL %>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 代码时加载该配置映射。瞧!

原文由 Hendrik M Halkow 发布,翻译遵循 CC BY-SA 4.0 许可协议

我在这里为那些仍然有问题的人添加我的 工作解决方案。我确实认为@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.[profile] 文件来设置环境变量。例如 .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;'

这使我能够拥有可以在许多环境中运行的运行时可配置图像。我知道这有点麻烦。但是看到很多人都是这样做的。

希望这对某人有帮助。

原文由 NehaM 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题