使用 docker 和 nginx 在运行时更改环境变量(React、vite)

在工作中,我需要在运行时通过 docker 和 nginx 从 Azure Web 服务更改环境变量。我尝试了 thisthis 和一些类似的解决方案,但我无法让它们中的任何一个工作。

我也找不到任何在线解决方案或任何解释这是否可能的文章/线程/帖子,我总是找到 vite statically 在构建时替换 env 变量的文本。

在我们的 CI/CD 管道期间,vite 获取了环境变量,但我们的 Azure 管理员希望能够从 Azure 配置它们,只是为了这种情况。

有谁知道这是否可能,或者可能有解决方案或一些帮助,好吗? :)

stack overflow Change Environmet Variables at runtime (React, vite) with docker and nginx
原文答案
author avatar

接受的答案

我的解决方案是它应该与我的问题中的链接一起使用。我使用 use this 方法并且它有效,唯一需要考虑的是使用不同的变量名称/前缀(例如“APP...”),因此 vite 不会在构建时更改它们。我创建了一个配置文件来解析变量,例如,如果应用程序正在生产中,则它使用新变量“APP..”(从 nginx/docker 注入)或使用“VITE...” - 如果“ APP..”未定义。


答案:

作者头像

not 可以动态注入 Vite 环境变量。但是什么是可能的,是更改 window object 变量(在运行时分配它们)。
警告!!!不要通过窗口对象暴露任何敏感变量。您的前端应用程序源对任何使用它的人都是可见的

脚步:

  1. 创建你想要的 env 文件并将它们放在 <rootDir>/public 中。我们称它们为 env.jsenv-prod.js

  2. 在您的 env.jsenv-prod.js 内您想使用 var 关键字分配所需的变量。此外,您必须在源代码中引用这些值,例如 window.MY_VAR 才能使用它们。

  3. 在您的 <rootDir>/index.html 中创建一个脚本标签,如下所示:
    <script type="text/javascript" src="./env.js"></script>
    重要!!! type="text/javascript" 很重要,因为如果您指定模块, Vite 将在您的缩小 env.js 文件中包含您的 index.js 源代码。

  4. Vite 配置(可选):

    
    plugins: [react(), tsConfigPath()],
    build: {
    emptyOutDir: true, // deletes the dist folder before building
    },
    });

5.  `How to serve the env files on runtime` 。创建一个  `node`  服务器,它将为您的前端应用程序提供服务。但是在提供  `env.js`  文件之前,根据我们的  `process.env.ENVIRONMENT` ,您现在可以选择要提供的 env.js。假设我的节点服务器文件存储在  `<rootDir>/server/server.js` :

const express = require("express");
const path = require("path");

const app = express();

const env = process.env.ENVIRONMENT || "";

console.log("ENVIRONMENT:", env);

const envFile = path.resolve("public", env ? env-${env}.js : "env.js");

const indexFile = path.resolve("dist", "index.html");

app.use((req, res, next) => {
const url = req.originalUrl;
if (url.includes("env.js")) {
console.log("sending", envFile);
// instead of env.js we send our desired env file
res.sendFile(envFile);
return;
}
next();
});

app.use(express.static(path.resolve("dist")));
app.get("*", (req, res) => {
res.sendFile(indexFile);
});

app.listen(8000);



6. 在终端中运行  `node ./server/sever.js`  命令时为您的应用程序构建提供服务。

7. **最后:**
    我的  `env.js`  包含  `var RUNTIME_VAR = 'test'` 
    我的  `env-prod.js`  包含  `var RUNTIME_VAR = 'prod'` 
    在我将  `process.env.ENVIRONMENT`  设置为  `prod`  之后。我得到了这个文件: [![enter image description here](https://i.stack.imgur.com/1Pcqg.png) ](https://i.stack.imgur.com/1Pcqg.png)
作者头像

您可以以 YAML 格式设置变量,并根据您的要求相应地更新它们。

以下是我们用作模板的示例 YAML 格式:

#Set variables once
variables:
  configuration: debug
  platform: x64

steps:

#Use them once
- task: MSBuild@1
  inputs:
    solution: solution1.sln
    configuration: $(configuration) # Use the variable
    platform: $(platform)

#Use them again
- task: MSBuild@1
  inputs:
    solution: solution2.sln
    configuration: $(configuration) # Use the variable
    platform: $(platform)

检查此 SO 以获得更多见解以了解托管在 azure Web 应用程序中的环境变量

作者头像

我想出了一个解决方案并将其作为包发布到 npm 注册表。

使用此解决方案,您无需更改任何代码:

// src/index.js
console.log(`API base URL is: ${import.meta.env.API_BASE_URL}.`);

它将构建步骤分为两个构建步骤:

在生产过程中,它会被一个占位符静态替换 import.meta.env

// dist/index.js
console.log(
  `API base URL is: ${"__import_meta_env_placeholder__".API_BASE_URL}.`
);

然后,您可以在任何地方运行包的 CLI 以将占位符替换为您的环境变量:

// dist/index.js
console.log(
  `API base URL is: ${{ API_BASE_URL: "https://httpbin.org" }.API_BASE_URL}.`
);
// > API base URL is: https://httpbin.org.

这是文档站点: https://iendeavor.github.io/import-meta-env/

随时提供任何反馈。

作者头像

首先在项目根目录下创建.env文件,然后在.env中定义一个变量

例如: VITE_APP_any = 'any'

然后将以下行添加到 vite.config.js :

export default defineConfig(({ command, mode }) => {

  const env = loadEnv(mode, process.cwd(), ""); //this line

  return { 
.
.
.

用法可以使用以下行

import.meta.env.VITE_APP_any

或者

process.env.VITE_APP_any